That demo uses Civic Auth in the frontend and forwards the authenticated Civic access token to a Python backend, which then passes it into CivicMCPClient(auth={"token": ...}).
Token exchange is server-side only. Your Civic client secret must never be shipped to a browser or untrusted environment.
Copy
# .env (server)CIVIC_CLIENT_ID=your_client_idCIVIC_CLIENT_SECRET=your_client_secret# Optional: lock tool access to a specific profile idCIVIC_PROFILE_ID=optional-profile-id
Copy
from civic_mcp_client import CivicMCPClientdef get_external_access_token() -> str: # Replace this with your IdP / external provider token fetch. return "external-token"client = CivicMCPClient( auth={ "token_exchange": { # Token exchange credentials (server-side only) "client_id": "your-client-id", "client_secret": "your-client-secret", "subject_token": get_external_access_token, "expires_in": 3600, # optional requested lifetime in seconds } }, civic_profile="optional-profile-id",)
This quick start uses a manually generated Civic access token for local testing. For a production-like frontend + Python backend setup, use the demo app above.
Copy
import asynciofrom civic_mcp_client import CivicMCPClientasync def main() -> None: client = CivicMCPClient( auth={"token": "your-civic-token-here"}, civic_profile="optional-profile-id", ) # Discover available tools from your configured toolkit tools = await client.get_tools() # Call a specific tool directly result = await client.call_tool( name="tool-name", args={"foo": "bar"}, ) print("Tools loaded:", len(tools)) print("Tool call result:", result) await client.close()asyncio.run(main())