Tutorial: Quem sou eu? (Who am I?)
Este tutorial irá guiá-lo pelo processo de configuração do MCP Auth para autenticar usuários e recuperar suas informações de identidade do servidor de autorização.
Após concluir este tutorial, você terá:
- ✅ Uma compreensão básica de como usar o MCP Auth para autenticar usuários.
- ✅ Um servidor MCP que oferece uma ferramenta para recuperar informações de identidade do usuário.
Visão geral (Overview)
O tutorial envolverá os seguintes componentes:
- Servidor MCP (MCP server): Um servidor MCP simples que utiliza os SDKs oficiais do MCP para lidar com requisições.
- MCP inspector: Uma ferramenta visual de testes para servidores MCP. Também atua como um cliente OAuth / OIDC para iniciar o fluxo de autorização e recuperar tokens de acesso.
- Servidor de autorização (Authorization server): Um provedor OAuth 2.1 ou OpenID Connect que gerencia identidades de usuários e emite tokens de acesso.
Aqui está um diagrama de alto nível da interação entre esses componentes:
Entenda seu servidor de autorização (Understand your authorization server)
Recuperando informações de identidade do usuário (Retrieving user identity information)
Para concluir este tutorial, seu servidor de autorização deve oferecer uma API para recuperar informações de identidade do usuário:
- Logto
- Keycloak
- OIDC
- OAuth 2
Logto é um provedor OpenID Connect que suporta o endpoint padrão userinfo para recuperar informações de identidade do usuário.
Para buscar um token de acesso que possa ser usado para acessar o endpoint userinfo, pelo menos dois escopos são necessários: openid
e profile
. Você pode continuar lendo, pois abordaremos a configuração de escopos mais adiante.
Keycloak é uma solução open-source de gerenciamento de identidade e acesso que suporta múltiplos protocolos, incluindo OpenID Connect (OIDC). Como um provedor OIDC, ele implementa o endpoint padrão userinfo para recuperar informações de identidade do usuário.
Para buscar um token de acesso que possa ser usado para acessar o endpoint userinfo, pelo menos dois escopos são necessários: openid
e profile
. Você pode continuar lendo, pois abordaremos a configuração de escopos mais adiante.
A maioria dos provedores OpenID Connect suporta o endpoint userinfo para recuperar informações de identidade do usuário.
Verifique a documentação do seu provedor para saber se ele suporta esse endpoint. Se seu provedor suporta OpenID Connect Discovery, você também pode verificar se o userinfo_endpoint
está incluído no documento de descoberta (resposta do endpoint .well-known/openid-configuration
).
Para buscar um token de acesso que possa ser usado para acessar o endpoint userinfo, pelo menos dois escopos são necessários: openid
e profile
. Verifique a documentação do seu provedor para ver o mapeamento de escopos para reivindicações de identidade do usuário.
Embora o OAuth 2.0 não defina uma maneira padrão de recuperar informações de identidade do usuário, muitos provedores implementam seus próprios endpoints para isso. Verifique a documentação do seu provedor para saber como recuperar informações de identidade do usuário usando um token de acesso e quais parâmetros são necessários para obter esse token ao invocar o fluxo de autorização.
Registro dinâmico de cliente (Dynamic Client Registration)
O registro dinâmico de cliente não é necessário para este tutorial, mas pode ser útil se você quiser automatizar o processo de registro do cliente MCP com seu servidor de autorização. Consulte O registro dinâmico de cliente é necessário? para mais detalhes.
Configure o servidor MCP (Set up the MCP server)
Usaremos os SDKs oficiais do MCP para criar um servidor MCP com uma ferramenta whoami
que recupera informações de identidade do usuário do servidor de autorização.
Crie um novo projeto (Create a new project)
- Python
- Node.js
mkdir mcp-server
cd mcp-server
uv init # Ou use `pipenv` ou `poetry` para criar um novo ambiente virtual
Configure um novo projeto Node.js:
mkdir mcp-server
cd mcp-server
npm init -y # Ou use `pnpm init`
npm pkg set type="module"
npm pkg set main="whoami.js"
npm pkg set scripts.start="node whoami.js"
Instale o MCP SDK e dependências (Install the MCP SDK and dependencies)
- Python
- Node.js
pip install "mcp[cli]" starlette uvicorn
Ou qualquer outro gerenciador de pacotes de sua preferência, como uv
ou poetry
.
npm install @modelcontextprotocol/sdk express
Ou qualquer outro gerenciador de pacotes de sua preferência, como pnpm
ou yarn
.
Crie o servidor MCP (Create the MCP server)
Primeiro, vamos criar um servidor MCP que implementa uma ferramenta whoami
.
- Python
- Node.js
Crie um arquivo chamado whoami.py
e adicione o seguinte código:
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from typing import Any
mcp = FastMCP("WhoAmI")
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Uma ferramenta que retorna as informações do usuário atual."""
return {"error": "Not authenticated"}
app = Starlette(
routes=[Mount('/', app=mcp.sse_app())]
)
Execute o servidor com:
uvicorn whoami:app --host 0.0.0.0 --port 3001
Como a implementação atual do MCP inspector não lida com fluxos de autorização, usaremos a abordagem SSE para configurar o servidor MCP. Atualizaremos o código aqui assim que o MCP inspector suportar fluxos de autorização.
Você também pode usar pnpm
ou yarn
se preferir.
Crie um arquivo chamado whoami.js
e adicione o seguinte código:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express from 'express';
// Crie um servidor MCP
const server = new McpServer({
name: 'WhoAmI',
version: '0.0.0',
});
// Adicione uma ferramenta ao servidor que retorna as informações do usuário atual
server.tool('whoami', async () => {
return {
content: [{ type: 'text', text: JSON.stringify({ error: 'Not authenticated' }) }],
};
});
// Abaixo está o código boilerplate da documentação do MCP SDK
const PORT = 3001;
const app = express();
const transports = {};
app.get('/sse', async (_req, res) => {
const transport = new SSEServerTransport('/messages', res);
transports[transport.sessionId] = transport;
res.on('close', () => {
delete transports[transport.sessionId];
});
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
const sessionId = String(req.query.sessionId);
const transport = transports[sessionId];
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
res.status(400).send('No transport found for sessionId');
}
});
app.listen(PORT);
Execute o servidor com:
npm start
Inspecione o servidor MCP (Inspect the MCP server)
Clone e execute o MCP inspector (Clone and run MCP inspector)
Agora que temos o servidor MCP em execução, podemos usar o MCP inspector para ver se a ferramenta whoami
está disponível.
Devido à limitação da implementação atual, fizemos um fork do MCP inspector para torná-lo mais flexível e escalável para autenticação e autorização. Também enviamos um pull request para o repositório original para incluir nossas alterações.
Para executar o MCP inspector, você pode usar o seguinte comando (Node.js é necessário):
git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run dev
Em seguida, abra seu navegador e acesse http://localhost:6274/
(ou outro URL exibido no terminal) para acessar o MCP inspector.
Conecte o MCP inspector ao servidor MCP (Connect MCP inspector to the MCP server)
Antes de prosseguir, verifique a seguinte configuração no MCP inspector:
- Tipo de transporte (Transport Type): Defina como
SSE
. - URL: Defina como a URL do seu servidor MCP. No nosso caso, deve ser
http://localhost:3001/sse
.
Agora você pode clicar no botão "Connect" para ver se o MCP inspector consegue se conectar ao servidor MCP. Se tudo estiver correto, você verá o status "Connected" no MCP inspector.
Ponto de verificação: Execute a ferramenta whoami
(Checkpoint: Run the whoami
tool)
- No menu superior do MCP inspector, clique na guia "Tools".
- Clique no botão "List Tools".
- Você deve ver a ferramenta
whoami
listada na página. Clique nela para abrir os detalhes da ferramenta. - Você deve ver o botão "Run Tool" no lado direito. Clique nele para executar a ferramenta.
- Você deve ver o resultado da ferramenta com a resposta JSON
{"error": "Not authenticated"}
.
Integre com seu servidor de autorização (Integrate with your authorization server)
Para concluir esta seção, há várias considerações a serem levadas em conta:
A URL do emissor do seu servidor de autorização (The issuer URL of your authorization server)
Normalmente, é a URL base do seu servidor de autorização, como https://auth.example.com
. Alguns provedores podem ter um caminho como https://example.logto.app/oidc
, então certifique-se de verificar a documentação do seu provedor.
Como recuperar os metadados do servidor de autorização (How to retrieve the authorization server metadata)
- Se seu servidor de autorização estiver em conformidade com o OAuth 2.0 Authorization Server Metadata ou OpenID Connect Discovery, você pode usar as utilidades integradas do MCP Auth para buscar os metadados automaticamente.
- Se seu servidor de autorização não estiver em conformidade com esses padrões, você precisará especificar manualmente a URL dos metadados ou endpoints na configuração do servidor MCP. Verifique a documentação do seu provedor para os endpoints específicos.
Como registrar o MCP inspector como cliente em seu servidor de autorização (How to register the MCP inspector as a client in your authorization server)
- Se seu servidor de autorização suporta Dynamic Client Registration, você pode pular esta etapa, pois o MCP inspector se registrará automaticamente como cliente.
- Se seu servidor de autorização não suporta Dynamic Client Registration, você precisará registrar manualmente o MCP inspector como cliente em seu servidor de autorização.
Como recuperar informações de identidade do usuário e como configurar os parâmetros da solicitação de autorização (How to retrieve user identity information and how to configure the authorization request parameters)
-
Para provedores OpenID Connect: normalmente você precisa solicitar pelo menos os escopos
openid
eprofile
ao iniciar o fluxo de autorização. Isso garantirá que o token de acesso retornado pelo servidor de autorização contenha os escopos necessários para acessar o endpoint userinfo para recuperar informações de identidade do usuário.Nota: Alguns provedores podem não suportar o endpoint userinfo.
-
Para provedores OAuth 2.0 / OAuth 2.1: verifique a documentação do seu provedor para saber como recuperar informações de identidade do usuário usando um token de acesso e quais parâmetros são necessários para obter esse token ao invocar o fluxo de autorização.
Embora cada provedor possa ter seus próprios requisitos específicos, as etapas a seguir irão guiá-lo pelo processo de integração do MCP inspector e do servidor MCP com configurações específicas do provedor.
Registre o MCP inspector como cliente (Register MCP inspector as a client)
- Logto
- Keycloak
- OIDC
- OAuth 2
Integrar com o Logto é simples, pois é um provedor OpenID Connect que suporta o endpoint padrão userinfo para recuperar informações de identidade do usuário.
Como o Logto ainda não suporta Dynamic Client Registration, você precisará registrar manualmente o MCP inspector como cliente em seu tenant Logto:
- Abra seu MCP inspector, clique no botão "OAuth Configuration". Copie o valor Redirect URL (auto-populated), que deve ser algo como
http://localhost:6274/oauth/callback
. - Faça login no Logto Console (ou seu Logto Console auto-hospedado).
- Navegue até a aba "Applications", clique em "Create application". No final da página, clique em "Create app without framework".
- Preencha os detalhes do aplicativo e clique em "Create application":
- Selecione um tipo de aplicativo: Escolha "Single-page application".
- Nome do aplicativo: Insira um nome para seu aplicativo, por exemplo, "MCP Inspector".
- Na seção "Settings / Redirect URIs", cole o valor Redirect URL (auto-populated) que você copiou do MCP inspector. Em seguida, clique em "Save changes" na barra inferior.
- No cartão superior, você verá o valor "App ID". Copie-o.
- Volte ao MCP inspector e cole o valor "App ID" na seção "OAuth Configuration" em "Client ID".
- Insira o valor
{"scope": "openid profile email"}
no campo "Auth Params". Isso garantirá que o token de acesso retornado pelo Logto contenha os escopos necessários para acessar o endpoint userinfo.
Keycloak é uma solução open-source de gerenciamento de identidade e acesso que suporta o protocolo OpenID Connect.
Embora o Keycloak suporte registro dinâmico de cliente, seu endpoint de registro de cliente não suporta CORS, impedindo que a maioria dos clientes MCP se registrem diretamente. Portanto, precisaremos registrar nosso cliente manualmente.
Embora o Keycloak possa ser instalado de várias formas (bare metal, kubernetes, etc.), para este tutorial, usaremos Docker para uma configuração rápida e simples.
Vamos configurar uma instância Keycloak e ajustá-la para nossas necessidades:
- Primeiro, execute uma instância Keycloak usando Docker conforme a documentação oficial:
docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.4 start-dev
-
Acesse o Keycloak Admin Console (http://localhost:8080/admin) e faça login com estas credenciais:
- Usuário:
admin
- Senha:
admin
- Usuário:
-
Crie um novo Realm:
- Clique em "Create Realm" no canto superior esquerdo
- Digite
mcp-realm
no campo "Realm name" - Clique em "Create"
-
Crie um usuário de teste:
- Clique em "Users" no menu à esquerda
- Clique em "Create new user"
- Preencha os detalhes do usuário:
- Username:
testuser
- Nome e sobrenome podem ser quaisquer valores
- Username:
- Clique em "Create"
- Na aba "Credentials", defina uma senha e desmarque "Temporary"
-
Registre o MCP Inspector como cliente:
- Abra seu MCP inspector, clique no botão "OAuth Configuration". Copie o valor Redirect URL (auto-populated), que deve ser algo como
http://localhost:6274/oauth/callback
. - No Keycloak Admin Console, clique em "Clients" no menu à esquerda
- Clique em "Create client"
- Preencha os detalhes do cliente:
- Tipo de cliente: Selecione "OpenID Connect"
- Client ID: Digite
mcp-inspector
- Clique em "Next"
- Na página "Capability config":
- Certifique-se de que "Standard flow" está habilitado
- Clique em "Next"
- Na página "Login settings":
- Cole a URL de callback do MCP Inspector em "Valid redirect URIs"
- Digite
http://localhost:6274
em "Web origins" - Clique em "Save"
- Copie o "Client ID" (que é
mcp-inspector
)
- Abra seu MCP inspector, clique no botão "OAuth Configuration". Copie o valor Redirect URL (auto-populated), que deve ser algo como
-
De volta ao MCP Inspector:
- Cole o Client ID copiado no campo "Client ID" na seção "OAuth Configuration"
- Insira o seguinte valor no campo "Auth Params" para solicitar os escopos necessários:
{ "scope": "openid profile email" }
Este é um guia genérico de integração com provedores OpenID Connect. Verifique a documentação do seu provedor para detalhes específicos.
Se seu provedor OpenID Connect suporta Dynamic Client Registration, você pode ir diretamente para o passo 8 abaixo para configurar o MCP inspector; caso contrário, será necessário registrar manualmente o MCP inspector como cliente em seu provedor OpenID Connect:
- Abra seu MCP inspector, clique no botão "OAuth Configuration". Copie o valor Redirect URL (auto-populated), que deve ser algo como
http://localhost:6274/oauth/callback
. - Faça login no console do seu provedor OpenID Connect.
- Navegue até a seção "Applications" ou "Clients" e crie um novo aplicativo ou cliente.
- Se seu provedor exigir um tipo de cliente, selecione "Single-page application" ou "Public client".
- Após criar o aplicativo, será necessário configurar a URI de redirecionamento. Cole o valor Redirect URL (auto-populated) que você copiou do MCP inspector.
- Encontre o "Client ID" ou "Application ID" do aplicativo recém-criado e copie-o.
- Volte ao MCP inspector e cole o valor "Client ID" na seção "OAuth Configuration" em "Client ID".
- Para provedores OpenID Connect padrão, você pode inserir o seguinte valor no campo "Auth Params" para solicitar os escopos necessários para acessar o endpoint userinfo:
{ "scope": "openid profile email" }
Este é um guia genérico de integração com provedores OAuth 2.0 / OAuth 2.1. Verifique a documentação do seu provedor para detalhes específicos.
Se seu provedor OAuth 2.0 / OAuth 2.1 suporta Dynamic Client Registration, você pode ir diretamente para o passo 8 abaixo para configurar o MCP inspector; caso contrário, será necessário registrar manualmente o MCP inspector como cliente em seu provedor OAuth 2.0 / OAuth 2.1:
- Abra seu MCP inspector, clique no botão "OAuth Configuration". Copie o valor Redirect URL (auto-populated), que deve ser algo como
http://localhost:6274/oauth/callback
. - Faça login no console do seu provedor OAuth 2.0 / OAuth 2.1.
- Navegue até a seção "Applications" ou "Clients" e crie um novo aplicativo ou cliente.
- Se seu provedor exigir um tipo de cliente, selecione "Single-page application" ou "Public client".
- Após criar o aplicativo, será necessário configurar a URI de redirecionamento. Cole o valor Redirect URL (auto-populated) que você copiou do MCP inspector.
- Encontre o "Client ID" ou "Application ID" do aplicativo recém-criado e copie-o.
- Volte ao MCP inspector e cole o valor "Client ID" na seção "OAuth Configuration" em "Client ID".
- Leia a documentação do seu provedor para saber como recuperar tokens de acesso para informações de identidade do usuário. Pode ser necessário especificar os escopos ou parâmetros necessários para obter o token de acesso. Por exemplo, se seu provedor exigir o escopo
profile
para acessar informações de identidade do usuário, você pode inserir o seguinte valor no campo "Auth Params":
{ "scope": "profile" }
Configure o MCP auth (Set up MCP auth)
No seu projeto do servidor MCP, você precisa instalar o SDK MCP Auth e configurá-lo para usar os metadados do seu servidor de autorização.
- Python
- Node.js
Primeiro, instale o pacote mcpauth
:
pip install mcpauth
Ou qualquer outro gerenciador de pacotes de sua preferência, como uv
ou poetry
.
Primeiro, instale o pacote mcp-auth
:
npm install mcp-auth
O MCP Auth requer os metadados do servidor de autorização para poder inicializar. Dependendo do seu provedor:
- Logto
- Keycloak
- OIDC
- OAuth 2
A URL do emissor pode ser encontrada na página de detalhes do seu aplicativo no Logto Console, na seção "Endpoints & Credentials / Issuer endpoint". Deve ser algo como https://my-project.logto.app/oidc
.
- Python
- Node.js
Atualize o whoami.py
para incluir a configuração do MCP Auth:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Substitua pelo endpoint do seu emissor
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Atualize o whoami.js
para incluir a configuração do MCP Auth:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Substitua pelo endpoint do seu emissor
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Agora, precisamos criar um verificador personalizado de token de acesso (Access token) que buscará as informações de identidade do usuário no servidor de autorização usando o token de acesso fornecido pelo inspetor MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
:param token: O Bearer token recebido do inspetor MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # O provedor deve suportar o endpoint userinfo
if not endpoint:
raise ValueError(
"O endpoint userinfo não está configurado nos metadados do servidor de autenticação."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Cabeçalho padrão Bearer token
)
response.raise_for_status() # Garante que um erro seja lançado para erros HTTP
json = response.json() # Analisa a resposta JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
issuer=issuer, # Usa o emissor dos metadados
claims=json, # Inclui todas as reivindicações (campos JSON) retornadas pelo endpoint userinfo
)
# `AuthInfo` é um modelo Pydantic, então erros de validação geralmente significam que a resposta não correspondeu
# à estrutura esperada
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Lida com outras exceções que podem ocorrer durante a requisição
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
* Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('O endpoint userinfo não está configurado nos metadados do servidor');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
clientId: '', // O Client ID não é usado neste exemplo, mas pode ser definido se necessário
scopes: [],
claims: userInfo,
};
};
A URL do emissor pode ser encontrada no Keycloak Admin Console. Em seu 'mcp-realm', navegue até a seção "Realm settings / Endpoints" e clique no link "OpenID Endpoint Configuration". O campo issuer
no documento JSON conterá sua URL de emissor, que deve ser algo como http://localhost:8080/realms/mcp-realm
.
- Python
- Node.js
Atualize o whoami.py
para incluir a configuração do MCP Auth:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Substitua pelo endpoint do seu emissor
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Atualize o whoami.js
para incluir a configuração do MCP Auth:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Substitua pelo endpoint do seu emissor
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Agora, precisamos criar um verificador personalizado de token de acesso (Access token) que buscará as informações de identidade do usuário no servidor de autorização usando o token de acesso fornecido pelo inspetor MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
:param token: O Bearer token recebido do inspetor MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # O provedor deve suportar o endpoint userinfo
if not endpoint:
raise ValueError(
"O endpoint userinfo não está configurado nos metadados do servidor de autenticação."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Cabeçalho padrão Bearer token
)
response.raise_for_status() # Garante que um erro seja lançado para erros HTTP
json = response.json() # Analisa a resposta JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
issuer=issuer, # Usa o emissor dos metadados
claims=json, # Inclui todas as reivindicações (campos JSON) retornadas pelo endpoint userinfo
)
# `AuthInfo` é um modelo Pydantic, então erros de validação geralmente significam que a resposta não correspondeu
# à estrutura esperada
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Lida com outras exceções que podem ocorrer durante a requisição
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
* Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('O endpoint userinfo não está configurado nos metadados do servidor');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
clientId: '', // O Client ID não é usado neste exemplo, mas pode ser definido se necessário
scopes: [],
claims: userInfo,
};
};
O código a seguir também assume que o servidor de autorização suporta o endpoint userinfo para recuperar informações de identidade do usuário. Se seu provedor não suportar esse endpoint, será necessário verificar a documentação do seu provedor para o endpoint específico e substituir a variável do endpoint userinfo pela URL correta.
- Python
- Node.js
Atualize o whoami.py
para incluir a configuração do MCP Auth:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Substitua pelo endpoint do seu emissor
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Atualize o whoami.js
para incluir a configuração do MCP Auth:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Substitua pelo endpoint do seu emissor
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Em alguns casos, a resposta do provedor pode estar malformada ou não estar em conformidade com o formato de metadados esperado. Se você tem certeza de que o provedor está em conformidade, é possível transpilar os metadados através da opção de configuração:
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...outras opções
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...outras opções
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Se o seu provedor não suportar OpenID Connect Discovery, você pode especificar manualmente a URL de metadados ou os endpoints. Confira Outras formas de inicializar o MCP Auth para mais detalhes.
Agora, precisamos criar um verificador personalizado de token de acesso (Access token) que buscará as informações de identidade do usuário no servidor de autorização usando o token de acesso fornecido pelo inspetor MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
:param token: O Bearer token recebido do inspetor MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # O provedor deve suportar o endpoint userinfo
if not endpoint:
raise ValueError(
"O endpoint userinfo não está configurado nos metadados do servidor de autenticação."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Cabeçalho padrão Bearer token
)
response.raise_for_status() # Garante que um erro seja lançado para erros HTTP
json = response.json() # Analisa a resposta JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
issuer=issuer, # Usa o emissor dos metadados
claims=json, # Inclui todas as reivindicações (campos JSON) retornadas pelo endpoint userinfo
)
# `AuthInfo` é um modelo Pydantic, então erros de validação geralmente significam que a resposta não correspondeu
# à estrutura esperada
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Lida com outras exceções que podem ocorrer durante a requisição
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
* Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('O endpoint userinfo não está configurado nos metadados do servidor');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' é uma reivindicação padrão para o sujeito (ID do usuário)
clientId: '', // O Client ID não é usado neste exemplo, mas pode ser definido se necessário
scopes: [],
claims: userInfo,
};
};
Como mencionamos anteriormente, o OAuth 2.0 não define uma maneira padrão de recuperar informações de identidade do usuário. O código a seguir assume que seu provedor possui um endpoint específico para recuperar informações de identidade do usuário usando um token de acesso. Você precisará verificar a documentação do seu provedor para o endpoint específico e substituir a variável do endpoint userinfo pela URL correta.
- Python
- Node.js
Atualize o whoami.py
para incluir a configuração do MCP Auth:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Substitua pelo endpoint do seu emissor
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OAUTH)
mcp_auth = MCPAuth(server=auth_server_config)
Atualize o whoami.js
para incluir a configuração do MCP Auth:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Substitua pelo endpoint do seu emissor
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oauth' }),
});
Em alguns casos, a resposta do provedor pode estar malformada ou não estar em conformidade com o formato de metadados esperado. Se você tem certeza de que o provedor está em conformidade, é possível transpilar os metadados através da opção de configuração:
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...outras opções
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...outras opções
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Se o seu provedor não suportar Metadados do servidor de autorização OAuth 2.0, você pode especificar manualmente a URL de metadados ou os endpoints. Confira Outras formas de inicializar o MCP Auth para mais detalhes.
Agora, precisamos criar um verificador personalizado de token de acesso (Access token) que buscará as informações de identidade do usuário no servidor de autorização usando o token de acesso fornecido pelo inspetor MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
:param token: O Bearer token recebido do inspetor MCP.
"""
try:
# O código a seguir assume que seu servidor de autorização possui um endpoint para buscar informações do usuário
# usando o token de acesso emitido pelo fluxo de autorização.
# Ajuste a URL e os headers conforme necessário com base na API do seu provedor.
response = requests.get(
"https://your-authorization-server.com/userinfo",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status() # Garante que um erro será lançado para erros HTTP
json = response.json() # Analisa a resposta JSON
# O código a seguir assume que a resposta de informações do usuário é um objeto com um campo 'sub' que
# identifica o usuário. Você pode precisar ajustar isso conforme a API do seu provedor.
return AuthInfo(
token=token,
subject=json.get("sub"),
issuer=auth_issuer, # Use o emissor configurado
claims=json, # Inclui todas as reivindicações (claims) retornadas pelo endpoint
)
# `AuthInfo` é um modelo Pydantic, então erros de validação geralmente significam que a resposta não correspondeu
# à estrutura esperada
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Lida com outras exceções que podem ocorrer durante a requisição
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Verifica o Bearer token fornecido buscando informações do usuário no servidor de autorização.
* Se o token for válido, retorna um objeto `AuthInfo` contendo as informações do usuário.
*/
const verifyToken = async (token) => {
// O código a seguir assume que seu servidor de autorização possui um endpoint para buscar informações do usuário
// usando o token de acesso emitido pelo fluxo de autorização.
// Ajuste a URL e os headers conforme necessário com base na API do seu provedor.
const response = await fetch('https://your-authorization-server.com/userinfo', {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
// O código a seguir assume que a resposta de informações do usuário é um objeto com um campo 'sub' que
// identifica o usuário. Você pode precisar ajustar isso conforme a API do seu provedor.
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer: authIssuer,
subject: String(userInfo.sub), // Ajuste conforme o campo de ID do usuário do seu provedor
clientId: '', // O Client ID não é usado neste exemplo, mas pode ser definido se necessário
scopes: [],
claims: userInfo,
};
};
Atualize o servidor MCP (Update MCP server)
Estamos quase lá! É hora de atualizar o servidor MCP para aplicar a rota e o middleware do MCP Auth, e então fazer a ferramenta whoami
retornar as informações reais de identidade do usuário.
- Python
- Node.js
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Uma ferramenta que retorna as informações do usuário atual."""
return (
mcp_auth.auth_info.claims
if mcp_auth.auth_info # Isso será preenchido pelo middleware Bearer auth
else {"error": "Not authenticated"}
)
# ...
bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
routes=[
# Adicione a rota de metadados (`/.well-known/oauth-authorization-server`)
mcp_auth.metadata_route(),
# Proteja o servidor MCP com o middleware Bearer auth
Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
],
)
server.tool('whoami', ({ authInfo }) => {
return {
content: [
{ type: 'text', text: JSON.stringify(authInfo?.claims ?? { error: 'Not authenticated' }) },
],
};
});
// ...
app.use(mcpAuth.delegatedRouter());
app.use(mcpAuth.bearerAuth(verifyToken));
Ponto de verificação: Execute a ferramenta whoami
com autenticação (Checkpoint: Run the whoami
tool with authentication)
Reinicie seu servidor MCP e abra o MCP inspector no navegador. Ao clicar no botão "Connect", você deve ser redirecionado para a página de login do seu servidor de autorização.
Depois de fazer login e retornar ao MCP inspector, repita as ações que fizemos no ponto de verificação anterior para executar a ferramenta whoami
. Desta vez, você deve ver as informações de identidade do usuário retornadas pelo servidor de autorização.
- Python
- Node.js
Confira o repositório do MCP Auth Python SDK para o código completo do servidor MCP (versão OIDC).
Confira o repositório do MCP Auth Node.js SDK para o código completo do servidor MCP (versão OIDC). Este diretório contém versões em TypeScript e JavaScript do código.
Notas finais (Closing notes)
🎊 Parabéns! Você concluiu com sucesso o tutorial. Vamos recapitular o que fizemos:
- Configuração de um servidor MCP básico com a ferramenta
whoami
- Integração do servidor MCP com um servidor de autorização usando MCP Auth
- Configuração do MCP Inspector para autenticar usuários e recuperar suas informações de identidade
Você também pode explorar alguns tópicos avançados, incluindo:
- Uso de JWT (JSON Web Token) para autenticação e autorização
- Aproveitamento de indicadores de recurso (RFC 8707) para especificar os recursos acessados
- Implementação de mecanismos personalizados de controle de acesso, como controle de acesso baseado em papel (RBAC) ou controle de acesso baseado em atributos (ABAC)
Não deixe de conferir outros tutoriais e a documentação para aproveitar ao máximo o MCP Auth.