Skip to main content
Glama
atulram

Keycloak Realm Inspector

by atulram

Keycloak Realm Inspector

一个纯粹作为OAuth 2.0受保护资源的MCP服务器,用于KeyConf 2026上关于Client ID Metadata Documents(draft-ietf-oauth-client-id-metadata-document-02)的演讲。

它不签发任何东西——没有/authorize、没有/token、没有客户端密钥。Keycloak签发令牌;本服务器根据Keycloak的JWKS验证这些令牌,提供RFC 9728发现服务,并暴露三个工具,使CIMD在资源服务器内部可见。

三方,刻意分离

Keycloak

授权服务器。--features=cimdKC_HTTP_RELATIVE_PATH=/auth、端口8080

MCP客户端

在其控制的URL上发布元数据文档。该URL就是client_id。在端口9000上提供服务

本服务器

受保护资源。端口9001

本服务器不托管、不读取、也不获取客户端的元数据文档。 没有/client-metadata.json路由,也没有本地副本。Keycloak在/authorize过程中通过网络获取该URL。在本代码库中,该URL只会作为不透明字符串出现在azp声明中——这正是整个演示的意义所在,也是为什么该文档由独立端口上的独立进程提供。

Related MCP server: mcpauth

运行

假定Keycloak已启动,realm已创建,CIMD客户端策略已应用。客户端、其元数据文档和令牌助手与本仓库相邻,位于../cimd-demo/auth-server/目录下。

# terminal 1 — the client's document. Its own party, its own port.
cd ../cimd-demo/auth-server && python -m http.server 9000

# terminal 2 — the resource server
pip install -r requirements.txt
python server.py                     # http://localhost:9001

# terminal 3 — get a token, then point an MCP client at :9001/mcp
cd ../cimd-demo/auth-server && python get-token.py

流程

  1. 客户端在无令牌的情况下调用/mcp,收到带有WWW-Authenticate: Bearer ..., resource_metadata="…"的401响应。

  2. 客户端据此访问/.well-known/oauth-protected-resource/mcp,获知哪个授权服务器签发有效令牌。

  3. 客户端直接向Keycloak认证,以其元数据文档URL作为client_id。Keycloak获取该URL并据此创建客户端。

  4. 客户端携带bearer令牌重试/mcp

RFC 9728 §3.1将well-known段置于主机与资源路径之间,因此发现文档位于/.well-known/oauth-protected-resource/mcp。不带/mcp的裸路径返回404。

工具

  • whoami() —— 来自调用方令牌的subpreferred_usernameazpscopeexpiss,外加registered_via_cimd。仅读取令牌;不调用Keycloak,因此即使管理员凭据错误也能正常工作。

  • list_clients(only_cimd=False) —— 列出realm中的客户端,将形如URL的client_id排在前面,使调用方客户端出现在第一行。

  • get_client_metadata(client_id) —— Keycloak自身的客户端表示。这是Keycloak的派生视图,而不是已发布的文档。

CIMD的判定依据是client_idhttp://https://开头。形如URL的client_id就是识别标志。

get_client_metadata在返回前剥离secretregistrationAccessToken。两者都是有效的bearer凭据,该输出会展示在投影仪上,并被录制下来。

两个已知缺口

RFC 8707资源指示器。 audience=存在,但已在JWTVerifier中被注释掉。对令牌进行受众限制需要客户端在/authorize中发送resource,而Keycloak 26.7的CIMD路径尚未支持该参数(keycloak#45106, keycloak#45284)。因此令牌携带的是Keycloak通常的account受众,本服务器无法进行受众限制。该缺口有意保留可见。

不强制scope。 required_scopes未设置,因此realm中任何签名有效且未过期的令牌都会被接受——包括来自admin-cli密码授权的令牌。这在登台演示时很有用:用管理员令牌运行whoami()azp是不透明字符串),再用CIMD令牌运行一次(azp是URL),同一个工具、同一台服务器,差异只在一个字段。这也意味着你必须确定自己持有的是哪个令牌。

配置

所有变量均通过os.getenv读取,默认值为localhost。

变量

默认值

KEYCLOAK_BASE_URL

http://localhost:8080/auth

KEYCLOAK_REALM

cimd-demo

KEYCLOAK_ISSUER

{base}/realms/{realm}

KEYCLOAK_JWKS_URI

{issuer}/protocol/openid-connect/certs

MCP_BASE_URL

http://localhost:9001

PORT

9001

KEYCLOAK_ADMIN

admin

KEYCLOAK_ADMIN_PASSWORD

admin

KEYCLOAK_ISSUERKEYCLOAK_JWKS_URI分别独立配置,而非由彼此派生:在Kubernetes中,issuer是公网URL,因此iss与客户端看到的一致,而JWKS获取应指向集群内的Service。

fastmcp被固定为精确版本。认证接口面一直在变动——resource_server_url变成了base_urlAccessToken.claims在2.11.3中才出现——而allowed_client_redirect_uris在任何版本中都不是RemoteAuthProvider的参数,尽管文档所展示的与之相反。该参数属于OAuthProxy,而本服务器并不使用它。

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Drop-in OAuth 2.1 + Dynamic Client Registration for MCP servers, providing authentication middleware and token verification.
    20
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables secure MCP tool calls (add and multiply numbers) by validating OAuth2 tokens via Keycloak token introspection.
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/atulram/keycloak-realm-inspector'

If you have feedback or need assistance with the MCP directory API, please join our Discord server