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 two 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
| |-- error_invalid_field.json
| `-- onboarding_status.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
| `-- 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 only these two tools.
get_client_onboarding_status
Input:
{
"client_id": "123"
}Output:
{
"client_id": "123",
"status": "Completed",
"message": "Client onboarding completed successfully"
}get_client_basic_info
Input:
{
"client_id": "123",
"field": "name"
}Allowed field values:
namefamily
Output:
{
"client_id": "123",
"field": "name",
"value": "John"
}{
"client_id": "123",
"field": "family",
"value": "Doe"
}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 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/familyMCP JSON-RPC
List tools:
curl -X POST http://localhost:8000/mcp ^
-H "Content-Type: application/json" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}"Call tool:
curl -X POST http://localhost:8000/mcp ^
-H "Content-Type: application/json" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"get_client_onboarding_status\",\"arguments\":{\"client_id\":\"123\"}}}"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/familyAuthentication Placeholder
Authentication is intentionally disabled for local development.
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
https://example.ngrok-free.appinappPackage/plugin.json,appPackage/openapi.yaml, andappPackage/manifest.json.Replace the GUIDs in
appPackage/manifest.jsonwith real Microsoft Entra app and bot registration IDs.Zip the contents of
appPackage/, not the folder itself.Upload the zip in Teams Developer Portal or Microsoft 365 Agents Toolkit.
Example Copilot prompts:
Get onboarding status for client 123
What is the client's name?
What is the client's family name?
For client 123, get the family field
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
example.ngrok-free.appinappPackage/manifest.json,appPackage/plugin.json, andappPackage/openapi.yaml.In Microsoft Entra ID, create or reuse an app registration for the Teams bot placeholder.
In Azure Bot Service or Bot Framework registration, set the messaging endpoint to your bot endpoint if you add a real Teams bot implementation.
In Teams Developer Portal, import the app package zip.
Validate the manifest and test in a personal scope first.
This project includes bot manifest placeholders but does not implement a Bot Framework message handler. Copilot calls the MCP server/plugin action; the bot block is present for Teams app packaging and future Teams conversational extensions.
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": {
"client_id": "123",
"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.27.
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