Authorization login callback
Install the SDK:
pnpm add mcp-auth-webAPI environments (engineUrl is the base URL, without a path):
- Test: https://aim-api-test.proton-system.com
- Production: https://aim-api.proton-system.com
Full authorization callback URL: https://xxx.com/openapi/v1/mcp/authorization/callback
The SDK adds this path automatically.
Return credentials after login succeeds:
import { createMcpAuthClient } from 'mcp-auth-web'
const mcpAuth = createMcpAuthClient({
engineUrl: 'https://aim-api-test.proton-system.com',
})
mcpAuth.complete({
Authorization: `Bearer ${token}`,
})When login fails or the user cancels:
mcpAuth.fail({ code, message })
mcpAuth.cancel()Starting with mcp-auth-web@0.3.1, getMcpAuthErrorMessage(error) provides SDK-maintained, safe default messages in Chinese. Your UI displays them; use error codes for custom copy or translations. Catch errors from complete(), fail(), and cancel(). Do not unconditionally call fail() from a complete() catch, or expose credentials and authorization URLs from raw errors.
import { getMcpAuthErrorMessage } from 'mcp-auth-web'
try {
mcpAuth.complete({ Authorization: `Bearer ${token}` })
} catch (error) {
message.error(getMcpAuthErrorMessage(error))
}engineUrl is the Engine address supplied by the platform. complete directly accepts the credential Headers used by your MCP. The SDK reads exp from the Authorization Bearer JWT and generates expiresAt automatically, so callers do not pass an expiry.
The SDK automatically uses the HTTPS callback or the existing App authorization window. mcp-auth-web@0.3.0 changes the complete input shape; when upgrading, remove the headers wrapper and the manually supplied expiresAt. Omitting engineUrl continues to use the existing App authorization window.
If the method returns false, the current page has no available authorization return method:
if (!mcpAuth.isAvailable()) {
message.error('This environment does not support authorization callbacks')
}To verify, start authorization in App and finish login. Returning to App with “Authorized” means the integration succeeded. Production login and Engine URLs require device-accessible HTTPS with a valid certificate. Never record credentials or authorization URLs in logs, analytics, or error reports.
Common Tool risk annotations
Read Tool:
annotations: {
readOnlyHint: true
}Write Tool:
annotations: {
destructiveHint: true
}Tool types
1. List Tool
When a Tool returns candidates that users select before the selected value is filled into another Tool parameter, add this object at the root of outputSchema:
outputSchema: {
type: "object",
properties: {...}, // optional
"x-prerequisiteCandidate": {
itemsPath: "data",
valuePath: "id",
labelPath: "name"
}
}The three fields mean:
itemsPath: where the candidate array is located in the Tool result.valuePath: which field in each candidate becomes the value filled into the target parameter.labelPath: which field in each candidate is shown to the user.
For example, the Tool returns:
{
"data": [
{ "id": "1", "name": "Store A" },
{ "id": "2", "name": "Store B" }
]
}Then:
itemsPath: "data"means the candidate list is thedataarray in the result.valuePath: "id"means the selected item'sidis filled into the target Tool.labelPath: "name"means the selection card displays the item'sname.
Contract checklist
- Add
x-prerequisiteCandidateto list Tools. - Do not add
x-prerequisiteCandidateto detail or write Tools. - Add
readOnlyHint: trueto read Tools. - Add
destructiveHint: trueto write Tools. - Return a stable structure when a list is empty, such as
{"data":[]}. - The actual Tool result must match
x-prerequisiteCandidate.