Client Onboarding MCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Client Onboarding MCPCheck onboarding status for client 123"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Client Onboarding MCP for Microsoft Copilot and Teams
Minimal Python 3.12 project with:
MCP server with client-session authentication and five tools
Separate mock backend server
REST/OpenAPI facade
Microsoft 365 Copilot plugin package files
Microsoft Teams app manifest
Docker, tests, local setup, auth placeholders, and examples
Architecture:
[Microsoft Teams]
|
v
[Microsoft Copilot]
|
v
[MCP Server]
|
v
[Mock Backend Server]Folder Tree
.
|-- appPackage/
| |-- adaptive-cards/
| | `-- client-result.json
| |-- color.png
| |-- declarativeAgent.json
| |-- manifest.json
| |-- mcp-tools.json
| |-- openapi.yaml
| |-- outline.png
| |-- plugin.json
| `-- plugin.openapi.json
|-- examples/
| |-- curl.md
| |-- json-rpc.md
| |-- requests.http
| `-- responses/
| |-- basic_info_family.json
| |-- basic_info_name.json
| |-- auth_failed.json
| |-- auth_required.json
| |-- auth_success.json
| |-- error_invalid_field.json
| |-- facility_limit.json
| |-- onboarding_status.json
| `-- outreach_summary.json
|-- mcp_server/
| |-- __init__.py
| |-- __main__.py
| |-- app.py
| |-- auth.py
| |-- backend_client.py
| |-- config.py
| |-- errors.py
| |-- jsonrpc.py
| |-- logging_config.py
| |-- mcp_app.py
| |-- models.py
| |-- routes.py
| |-- session.py
| `-- tool_registry.py
|-- mock_backend/
| |-- __init__.py
| |-- __main__.py
| |-- app.py
| |-- config.py
| |-- logging_config.py
| |-- models.py
| `-- routes.py
|-- tests/
| |-- conftest.py
| |-- test_backend.py
| |-- test_mcp_http.py
| `-- test_tool_registry.py
|-- .env.example
|-- .vscode/launch.json
|-- Dockerfile
|-- docker-compose.yml
|-- main.py
|-- openapi.yaml
|-- pytest.ini
|-- requirements.txt
`-- tools.jsonTools
The MCP exposes these five tools.
authenticate_client
Input:
{
"client_id": "123",
"otp": "9632"
}Successful output:
{
"authenticated": true,
"client_id": "123",
"message": "Authentication successful"
}Failed output:
{
"authenticated": false,
"message": "Invalid OTP"
}Business tools use the authenticated client_id stored in the MCP session. For local HTTP tests, keep the same x-mcp-session-id header across calls.
get_client_onboarding_status
Input:
{}Output:
{
"client_id": "123",
"status": "Completed",
"message": "Client onboarding completed successfully"
}get_client_basic_info
Input:
{
"field": "name"
}Allowed field values:
namefamily
Output:
{
"client_id": "123",
"field": "name",
"value": "John"
}{
"client_id": "123",
"field": "family",
"value": "Doe"
}get_client_facility_limit
Input:
{}Output:
{
"client_id": "123",
"client_name": "John Doe",
"facility_limit_eur": 75000000,
"currency": "EUR",
"formatted_limit": "EUR 75,000,000"
}summarize_client_outreach
Input:
{}Output includes the outreach reasons, highlights, and total questions to answer:
{
"client_id": "123",
"client_name": "John Doe",
"outreach_count": 2,
"questions_to_answer_count": 5,
"reasons": ["Annual facility review", "Updated cash-flow forecast"],
"summary": "John Doe has 2 outreach items. Reasons: Annual facility review, Updated cash-flow forecast. You should answer 5 questions in total."
}Local Setup
Use Python 3.12.
python -m venv .venv312
.venv312\Scripts\activate
pip install -r requirements.txt
copy .env.example .envTerminal 1:
uvicorn mock_backend.app:app --host 0.0.0.0 --port 8001 --reloadTerminal 2:
uvicorn mcp_server.app:app --host 0.0.0.0 --port 8000 --reloadHealth checks:
curl http://localhost:8001/health
curl http://localhost:8000/healthREST API
OpenAPI 3.1 schema:
Static YAML:
openapi.yamlRuntime JSON:
http://localhost:8000/openapi.jsonRuntime YAML file endpoint:
http://localhost:8000/openapi.yaml
Endpoints:
curl -X POST http://localhost:8000/api/v1/authenticate \
-H "Content-Type: application/json" \
-H "x-mcp-session-id: demo-session" \
-d '{"client_id":"123","otp":"9632"}'
curl http://localhost:8000/api/v1/client/onboarding-status -H "x-mcp-session-id: demo-session"
curl http://localhost:8000/api/v1/client/basic-info/name -H "x-mcp-session-id: demo-session"
curl http://localhost:8000/api/v1/client/facility -H "x-mcp-session-id: demo-session"
curl http://localhost:8000/api/v1/client/outreach-summary -H "x-mcp-session-id: demo-session"
curl http://localhost:8000/api/v1/clients/123/onboarding-status
curl http://localhost:8000/api/v1/clients/123/basic-info/name
curl http://localhost:8000/api/v1/clients/123/basic-info/family
curl http://localhost:8000/api/v1/clients/123/facility
curl http://localhost:8000/api/v1/clients/123/outreach-summaryMCP JSON-RPC
List tools:
curl -X POST http://localhost:8000/mcp ^
-H "Content-Type: application/json" ^
-H "x-mcp-session-id: demo-session" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}"Authenticate first:
curl -X POST http://localhost:8000/mcp ^
-H "Content-Type: application/json" ^
-H "x-mcp-session-id: demo-session" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"authenticate_client\",\"arguments\":{\"client_id\":\"123\",\"otp\":\"9632\"}}}"Then call business tools with the same session ID and no client_id argument:
curl -X POST http://localhost:8000/mcp ^
-H "Content-Type: application/json" ^
-H "x-mcp-session-id: demo-session" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"get_client_onboarding_status\",\"arguments\":{}}}"The MCP Python SDK registration is in mcp_server/mcp_app.py. For stdio-style MCP testing:
python -m mcp_server.mcp_appMock Backend
The mock backend is a separate FastAPI service and returns hardcoded data only.
curl http://localhost:8001/status/123
curl http://localhost:8001/info/123/name
curl http://localhost:8001/info/123/family
curl http://localhost:8001/facility/123
curl http://localhost:8001/outreach/123/summaryMCP Client Session Authentication
MCP client-session authentication is enabled in the tool flow:
Tool:
authenticate_clientRequired input:
client_id,otpDemo OTP:
9632Storage: in-memory only
Session key:
x-mcp-session-idormcp-session-idheader for HTTP tests
If a business tool is called before authentication, the MCP tool returns:
{
"error": "AUTH_REQUIRED",
"message": "Please authenticate first using client_id and OTP"
}Production replacement points are marked in session.py:
Replace the hardcoded OTP with real OTP validation.
Load client/user mappings from a database.
Bind session IDs to Microsoft Entra ID or Teams user identity.
Store sessions in Redis or another shared session store.
API Key Placeholder
API key validation is intentionally disabled for local development. This is separate from the MCP client-session authentication tool.
Enable API key validation:
MCP_AUTH_REQUIRED=true
MCP_API_KEY_HEADER=x-api-key
MCP_API_KEY=local-dev-keyThen call:
curl http://localhost:8000/api/v1/clients/123/onboarding-status -H "x-api-key: local-dev-key"Production replacement points:
Replace
APIKeyAuthMiddlewarewith Microsoft Entra ID JWT validation.Register an app in Microsoft Entra ID.
Configure Teams bot and Copilot plugin auth references with the production app registration.
Store secrets in Azure Key Vault or a managed secret store.
Docker
docker compose up --buildServices:
MCP server:
http://localhost:8000Mock backend:
http://localhost:8001
Copilot Package
Package files are in appPackage/.
manifest.json: Microsoft 365/Teams app manifestdeclarativeAgent.json: declarative agent manifestplugin.json: Microsoft 365 Copilot plugin manifest usingRemoteMCPServerplugin.openapi.json: OpenAPI fallback plugin manifestmcp-tools.json: MCP tool discovery metadata mirror of the inline plugin metadataopenapi.yaml: OpenAPI schema for the REST facadecolor.pngandoutline.png: Teams package icons
Before packaging:
Replace the hosted domain in
appPackage/plugin.json,appPackage/openapi.yaml, andappPackage/manifest.jsonif you move away from the current Railway URL.Replace the app ID in
appPackage/manifest.jsonwith a real package ID before production publishing.Zip the contents of
appPackage/, not the folder itself.Upload the zip in Teams Developer Portal or Microsoft 365 Agents Toolkit.
Example Copilot prompts:
Authenticate client 123 with OTP 9632
Get my onboarding status
What is the client's name?
What is the client's family name?
What is the current limit on my company's facility?
Summarize my outreach highlights
Teams Local Testing
Start both local services.
Start an HTTPS tunnel:
ngrok http 8000Copy the HTTPS ngrok domain, for example
https://abc123.ngrok-free.app.Replace the hosted domain in
appPackage/manifest.json,appPackage/plugin.json, andappPackage/openapi.yaml.In Teams Developer Portal, import the app package zip.
Validate the manifest and test in a personal scope first.
This project is packaged as a Copilot declarative agent. It does not implement a Bot Framework message handler.
Error Handling Examples
Invalid basic info field through REST:
curl http://localhost:8000/api/v1/clients/123/basic-info/ageResponse shape:
{
"error": {
"code": "validation_error",
"message": "Request validation failed.",
"details": []
}
}Invalid MCP tool call:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_client_basic_info",
"arguments": {
"field": "age"
}
}
}Response shape:
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Tool arguments failed validation.",
"data": {
"code": "invalid_arguments",
"details": []
}
}
}Logging
Both services log requests with method, path, status code, and elapsed time.
Log levels:
MCP_LOG_LEVEL=INFO
BACKEND_LOG_LEVEL=INFOTests
pytest -qTests cover:
Mock backend responses
REST facade responses
MCP
tools/listMCP
tools/callTool validation
API Versioning Strategy
REST endpoints are versioned under /api/v1.
Recommended evolution:
Keep
/api/v1stable for existing Copilot plugins.Add
/api/v2for breaking response or parameter changes.Keep MCP tool names stable where possible.
Add new tool names for breaking tool contract changes.
Keep
operationIdvalues aligned with Copilot plugin function names.
References
Microsoft 365 Copilot plugins support REST APIs and MCP servers through declarative agent actions.
Current Microsoft plugin manifest schema version used here:
v2.4.Current Microsoft 365 app manifest schema used here:
v1.22.
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/rezapars/simple-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server