@@ -4,223 +4,263 @@ A collection of Python packages for KeyCard services, organized as a uv workspac
44
55## Quick Start
66
7- Get up and running with KeyCard's MCP (Model Context Protocol) integration in minutes :
7+ Choose the integration that best fits your MCP setup :
88
9- ### Install the Packages
9+ ## Quick Start with keycardai-mcp (Standard MCP)
10+
11+ For standard MCP servers using the official MCP Python SDK:
12+
13+ ### Install the Package
1014
1115``` bash
12- pip install mcp keycardai-mcp
16+ pip install keycardai-mcp
1317```
1418
15- or
19+ or
1620
1721``` bash
18- uv add mcp keycardai-mcp
22+ uv add keycardai-mcp
1923```
2024
21- ### Create Your First MCP Server
25+ ### Get Your KeyCard Zone ID
26+
27+ 1 . Sign up at [ keycard.ai] ( https://keycard.ai )
28+ 2 . Navigate to Zone Settings to get your zone ID
29+ 3 . Configure your preferred identity provider (Google, Microsoft, etc.)
30+ 4 . Create an MCP resource in your zone
31+
32+ ### Add Authentication to Your MCP Server
2233
2334``` python
2435from mcp.server.fastmcp import FastMCP
36+ from keycardai.mcp.server.auth import AuthProvider
2537
26- mcp = FastMCP(" Hello World" )
38+ # Your existing MCP server
39+ mcp = FastMCP(" My Secure MCP Server" )
2740
2841@mcp.tool ()
29- def hello_world ( name : str ) -> str :
30- return f " Hello, { name } ! "
42+ def my_protected_tool ( data : str ) -> str :
43+ return f " Processed: { data } "
3144
32- if __name__ == " __main__ " :
33- mcp.run( transport = " streamable-http " )
34- ```
35-
36- ### Run your MCP server
45+ # Add KeyCard authentication
46+ access = AuthProvider(
47+ zone_id = " your_zone_id_here " ,
48+ mcp_server_name = " My Secure MCP Server " ,
49+ )
3750
38- ``` bash
39- python server.py
51+ # Create authenticated app
52+ app = access.app(mcp)
4053```
4154
42- For more details, refer to the [ mcp] ( https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#streamable-http-transport ) documentation.
43-
44- ### Configure the remote MCP in your AI client, like [ Cursor] ( https://cursor.com/?from=home )
55+ ### Run with Authentication
4556
46- ``` json
47- {
48- "mcpServers" : {
49- "hello-world" : {
50- "url" : " http://localhost:8000/mcp"
51- }
52- }
53- }
57+ ``` bash
58+ pip install uvicorn
59+ uvicorn server:app
5460```
5561
56- ### Test the remote server with client
57-
58- <img src =" docs/images/cursor_hello_world_agent_call.png " alt =" Cursor Hello World Agent Call " width =" 500 " >
59-
60- ### Signup to Keycard and get your zone identifier
61-
62- Refer to [ docs] ( https://docs.keycard.ai/ ) on how to sign up. Navigate to Zone Settings to obtain the zone ID.
63-
64- <img src =" docs/images/keycard_zone_information.png " alt =" Keycard ZoneId Information " width =" 400 " >
65-
66- ### Configure Your Preferred Identity Provider
67-
68- <img src =" docs/images/keycard_identity_provider_config.png " alt =" Keycard Identity Provider Configuration " width =" 400 " >
69-
70- ### Setup MCP resource
71-
72- <img src =" docs/images/create_mcp_resource.png " alt =" Create MCP Resource " width =" 400 " >
73-
74- ### Add authentication to the MCP server
62+ ### Add Delegated Access (Optional)
7563
7664``` python
77- from mcp.server.fastmcp import FastMCP
78-
79- from keycardai.mcp.server.auth import AuthProvider
80-
81- # From the zone setting above
82- zone_id = " 90zqtq5lvtobrmyl3b0i0k2z1q"
65+ import os
66+ from mcp.server.fastmcp import FastMCP, Context
67+ from keycardai.mcp.server.auth import AuthProvider, AccessContext, BasicAuth
8368
69+ # Configure your provider with client credentials
8470access = AuthProvider(
85- zone_id = zone_id,
86- mcp_server_name = " Hello World Mcp" ,
71+ zone_id = " your_zone_id" ,
72+ mcp_server_name = " My MCP Server" ,
73+ auth = BasicAuth(
74+ os.getenv(" KEYCARD_CLIENT_ID" ),
75+ os.getenv(" KEYCARD_CLIENT_SECRET" )
76+ )
8777)
8878
89- mcp = FastMCP(" Minimal MCP" )
79+ mcp = FastMCP(" My MCP Server " )
9080
9181@mcp.tool ()
92- def hello_world (name : str ) -> str :
93- return f " Hello, { name} ! "
82+ @access.grant (" https://protected-api" )
83+ def protected_tool (ctx : Context, access_context : AccessContext, name : str ) -> str :
84+ # Use the access_context to call external APIs on behalf of the user
85+ token = access_context.access(" https://protected-api" ).access_token
86+ # Make authenticated API calls...
87+ return f " Protected data for { name} "
9488
95- # Create Starlette app to handle authorization flows
9689app = access.app(mcp)
9790```
9891
99- ### Run Your Server
100-
101- The authorization flows require additional handlers to advertise the metadata.
92+ ## Quick Start with keycardai-mcp-fastmcp (FastMCP)
10293
103- This is implemented using the underlying Starlette application. For more information, refer to the official [ mcp ] ( https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#streamablehttp-servers ) documentation.
94+ For FastMCP servers using the FastMCP framework:
10495
105- You can use any async server, for example [ uvicorn ] ( https://www.uvicorn.org/ ) :
96+ ### Install the Package
10697
10798``` bash
108- uv add uvicorn
99+ pip install keycardai-mcp-fastmcp
109100```
110101
111102or
112103
113104``` bash
114- pip install uvicorn
105+ uv add keycardai-mcp-fastmcp
115106```
116107
117- ``` bash
118- python -m uvicorn server:app
119- ```
108+ ### Get Your KeyCard Zone ID
120109
121- ### Authenticate in client
110+ 1 . Sign up at [ keycard.ai] ( https://keycard.ai )
111+ 2 . Navigate to Zone Settings to get your zone ID
112+ 3 . Configure your preferred identity provider (Google, Microsoft, etc.)
113+ 4 . Create an MCP resource in your zone
122114
123- < img src = " docs/images/cursor_authenticate.png " alt = " Cursor Authentication Prompt " width = " 500 " >
115+ ### Add Authentication to Your FastMCP Server
124116
117+ ``` python
118+ from fastmcp import FastMCP, Context
119+ from keycardai.mcp.integrations.fastmcp import AuthProvider
120+
121+ # Configure KeyCard authentication
122+ auth_provider = AuthProvider(
123+ zone_id = " your-zone-id" , # Get this from keycard.ai
124+ mcp_server_name = " My Secure FastMCP Server" ,
125+ mcp_base_url = " http://127.0.0.1:8000/"
126+ )
125127
126- ### 🎉 Your MCP server is now running with KeyCard authentication! 🎉
128+ # Get the RemoteAuthProvider for FastMCP
129+ auth = auth_provider.get_remote_auth_provider()
127130
128- ## Features
131+ # Create authenticated FastMCP server
132+ mcp = FastMCP(" My Secure FastMCP Server" , auth = auth)
129133
130- ### Delegated Access
134+ @mcp.tool ()
135+ def hello_world (name : str ) -> str :
136+ return f " Hello, { name} ! "
131137
132- You can use Keycard to allow MCP servers to access other resources on behalf of the user.
138+ if __name__ == " __main__" :
139+ mcp.run(transport = " streamable-http" )
140+ ```
133141
134- It automatically requests user consent and performs necessary secure exchanges to provide granular access to resources.
142+ ### Add Delegated Access (Optional)
135143
136- #### Configure credential provider
144+ ``` python
145+ from fastmcp import FastMCP, Context
146+ from keycardai.mcp.integrations.fastmcp import AuthProvider, AccessContext
147+
148+ # Configure KeyCard authentication
149+ auth_provider = AuthProvider(
150+ zone_id = " your-zone-id" ,
151+ mcp_server_name = " My Secure FastMCP Server" ,
152+ mcp_base_url = " http://127.0.0.1:8000/"
153+ )
137154
138- Configure a credential provider for your resource, for example Google Workspace.
155+ # Get the RemoteAuthProvider for FastMCP
156+ auth = auth_provider.get_remote_auth_provider()
139157
140- <img src =" docs/images/keycard_credential_provider_config.png " alt =" Keycard Credential Provider Configuration " width =" 400 " >
158+ # Create authenticated FastMCP server
159+ mcp = FastMCP(" My Secure FastMCP Server" , auth = auth)
141160
142- #### Configure protected resource
161+ # Example with token exchange for external API access
162+ @mcp.tool ()
163+ @auth_provider.grant (" https://api.example.com" )
164+ def call_external_api (ctx : Context, query : str ) -> str :
165+ # Get access context to check token exchange status
166+ access_context: AccessContext = ctx.get_state(" keycardai" )
167+
168+ # Check for errors before accessing token
169+ if access_context.has_errors():
170+ return f " Error: Failed to obtain access token - { access_context.get_errors()} "
171+
172+ # Access delegated token through context namespace
173+ token = access_context.access(" https://api.example.com" ).access_token
174+ # Use token to call external API
175+ return f " Results for { query} "
143176
144- Configure a protected resource, for example the Google Drive API.
177+ if __name__ == " __main__" :
178+ mcp.run(transport = " streamable-http" )
179+ ```
145180
146- < img src = " docs/images/keycard_resource_create.png " alt = " Keycard Resource Creation " width = " 400 " >
181+ ### Configure Your AI Client
147182
148- #### Allow access from MCP to protected resource
183+ Configure the remote MCP in your AI client, like [ Cursor ] ( https://cursor.com/?from=home ) :
149184
150- To allow the MCP server to make delegated calls to the API, set the dependency on the MCP server for the protected resource.
185+ ``` json
186+ {
187+ "mcpServers" : {
188+ "my-secure-server" : {
189+ "url" : " http://localhost:8000/mcp"
190+ }
191+ }
192+ }
193+ ```
151194
152- < img src = " docs/images/keycard_set_dependency.png " alt = " Keycard Set Dependency " width = " 400 " >
195+ ### 🎉 Your MCP server is now protected with KeyCard authentication! 🎉
153196
154- #### Give the MCP server identity secret
197+ ## Features
155198
156- In order for the MCP server to securely perform exchanges, it requires an identity secret.
199+ ### Delegated Access
157200
158- < img src = " docs/images/keycard_identity_configuration.png " alt = " Keycard Resource Identity " width = " 400 " >
201+ KeyCard allows MCP servers to access other resources on behalf of users with automatic consent and secure token exchange.
159202
160- Note: Keep the client_id and client_secret safe. We will use them in the next steps.
203+ #### Setup Protected Resources
161204
162- #### Add delegation control to tool calls
205+ 1 . ** Configure credential provider** (e.g., Google Workspace)
206+ 2 . ** Configure protected resource** (e.g., Google Drive API)
207+ 3 . ** Set MCP server dependencies** to allow delegated access
208+ 4 . ** Create client secret identity** for secure authentication
163209
164- Note: For demonstration, we will print a different message when access is granted.
165- In real use cases, you would use the token to make requests to downstream APIs.
166210
167- ``` python
168- import os
169- from mcp.server.fastmcp import FastMCP, Context
211+ ## Overview
170212
171- from keycardai.mcp.server.auth import AuthProvider, AccessContext, BasicAuth
213+ This workspace contains multiple Python packages that provide various KeyCard functionality:
172214
173- # From the zone setting above
174- zone_id = " 90zqtq5lvtobrmyl3b0i0k2z1q"
215+ - ** keycardai-oauth** : OAuth 2.0 implementation with support for RFC 8693 (Token Exchange)
216+ - ** keycardai-mcp** : Core MCP (Model Context Protocol) integration utilities for standard MCP servers
217+ - ** keycardai-mcp-fastmcp** : FastMCP-specific integration package with decorators and middleware
175218
176- access = AuthProvider(
177- zone_id = zone_id,
178- mcp_server_name = " Hello World Mcp" ,
179- auth = BasicAuth(os.getenv(" KEYCARD_CLIENT_ID" ), os.getenv(" KEYCARD_CLIENT_SECRET" ))
180- )
219+ ## Installation
181220
182- mcp = FastMCP( " Minimal MCP" )
221+ ### For Standard MCP Servers
183222
184- protected_resource_identifier = " https://protected-api "
223+ If you're using the official MCP Python SDK:
185224
186- @mcp.tool ()
187- @access.grant (protected_resource_identifier)
188- def hello_world (ctx : Context, access_context : AccessContext, name : str ) -> str :
189- msg = f " Hello, { name} ! "
190- if access_context.access(protected_resource_identifier).access_token:
191- msg = f " Hello, { name} ! I can see you have extra access "
192- return msg
193-
194- # Create Starlette app to handle authorization flows
195- app = access.app(mcp)
225+ ``` bash
226+ pip install keycardai-mcp
196227```
197228
198- #### Use obtained access to make API calls on behalf of users
229+ or
199230
200- <img src =" docs/images/cursor_delegated_access_example.png " alt =" Keycard Set Dependency " width =" 400 " >
231+ ``` bash
232+ uv add keycardai-mcp
233+ ```
201234
235+ ### For FastMCP Servers
202236
203- ## Overview
237+ If you're using the FastMCP framework:
204238
205- This workspace contains multiple Python packages that provide various KeyCard functionality:
239+ ``` bash
240+ pip install keycardai-mcp-fastmcp
241+ ```
206242
207- - ** keycardai-oauth** : OAuth 2.0 implementation with support for RFC 8693 (Token Exchange)
208- - ** keycardai-mcp** : Core MCP (Model Context Protocol) integration utilities
209- - ** keycardai-mcp-fastmcp** : FastMCP-specific integration package with decorators and middleware
243+ or
210244
211- ## Installation
245+ ``` bash
246+ uv add keycardai-mcp-fastmcp
247+ ```
212248
213- Install the SDK packages using pip:
249+ ### For OAuth Functionality Only
250+
251+ If you only need OAuth capabilities:
214252
215253``` bash
216- # Install individual packages as needed
217254pip install keycardai-oauth
218- pip install keycardai-mcp
219- pip install keycardai-mcp-fastmcp
255+ ```
220256
221- # Or install from source
257+ ### Install from Source
258+
259+ ``` bash
222260git clone git@github.com:keycardai/python-sdk.git
223261cd python-sdk
262+
263+ # Install specific packages as needed
224264pip install ./packages/oauth
225265pip install ./packages/mcp
226266pip install ./packages/mcp-fastmcp
0 commit comments