tools.
Limit which tools the model can call with allowed_tools.
Use require_approval when you want your app to pause and ask the end user before the tool runs.
Use X-On-Behalf-Of for the MKA1 API end user.
Pass upstream MCP server credentials in the MCP tool definition.
Call an MCP tool directly
Setrequire_approval to 'never' when the tool can run immediately.
mka1 llm responses create --body '{
"model": "auto",
"instructions": "You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.",
"input": "List my most recent Linear issue assigned to me.",
"store": true,
"stream": false,
"tools": [
{
"type": "mcp",
"server_label": "Linear MCP",
"server_description": "Access Linear issues through MCP.",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": {
"Authorization": "Bearer <linear-api-key>"
},
"require_approval": "never"
}
]
}' \
-H 'X-On-Behalf-Of: <end-user-id>'
import { SDK } from '@meetkai/mka1';
import type * as components from '@meetkai/mka1/models/components';
const mka1 = new SDK({
bearerAuth: `Bearer ${YOUR_API_KEY}`,
});
const response = await mka1.llm.responses.create({
xOnBehalfOf: '<end-user-id>', // optional — attribute the request to one of your end users
responsesCreateRequest: {
model: 'auto',
instructions:
'You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.',
input: 'List my most recent Linear issue assigned to me.',
store: true,
stream: false,
tools: [
{
type: 'mcp',
serverLabel: 'Linear MCP',
serverDescription: 'Access Linear issues through MCP.',
serverUrl: 'https://mcp.linear.app/mcp',
allowedTools: ['issues.list'],
headers: {
Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
},
requireApproval: 'never',
},
],
},
}) as components.ResponseObject;
// MCP tool calls appear as mcp_call items in the output
const mcpCalls = response.output.filter(
(item): item is components.MCPToolCall => item.type === 'mcp_call',
);
const assistantText = response.output
.filter(
(item): item is components.OutputMessage =>
item.type === 'message' && item.role === 'assistant',
)
.flatMap(item =>
item.content.flatMap(content =>
content.type === 'output_text' ? [content.text] : [],
),
)
.join('\n\n')
.trim();
console.log(assistantText);
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: '<mka1-api-key>',
baseURL: 'https://apigw.mka1.com/api/v1/llm/',
defaultHeaders: { 'X-On-Behalf-Of': '<end-user-id>' },
});
const response = await openai.responses.create({
model: 'auto',
instructions:
'You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.',
input: 'List my most recent Linear issue assigned to me.',
store: true,
stream: false,
tools: [
{
type: 'mcp',
server_label: 'Linear MCP',
server_description: 'Access Linear issues through MCP.',
server_url: 'https://mcp.linear.app/mcp',
allowed_tools: ['issues.list'],
headers: {
Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
},
require_approval: 'never',
},
],
});
// MCP tool calls appear as mcp_call items in the output
const mcpCall = response.output.find((item) => item.type === 'mcp_call');
const message = response.output.find((item) => item.type === 'message');
console.log(response.output_text);
using MeetKai.MKA1;
using MeetKai.MKA1.Types.Components;
var sdk = new SDK(
bearerAuth: "Bearer <mka1-api-key>",
serverUrl: "https://apigw.mka1.com"
);
var response = await sdk.Llm.Responses.CreateAsync(
new ResponsesCreateRequest()
{
Model = "auto",
Input = ResponsesCreateRequestInput.CreateStr(
"List my most recent Linear issue assigned to me."
),
}
);
// MCP tools require a running MCP server endpoint.
// The SDK constructs the same request shape as the TypeScript and curl examples.
Console.WriteLine(response);
from meetkai_mka1 import SDK
import os
sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")
response = sdk.llm.responses.create(
model="auto",
instructions="You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.",
input="List my most recent Linear issue assigned to me.",
store=True,
stream=False,
tools=[
{
"type": "mcp",
"server_label": "Linear MCP",
"server_description": "Access Linear issues through MCP.",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": {
"Authorization": f"Bearer {os.environ['LINEAR_API_KEY']}",
},
"require_approval": "never",
},
],
)
print(response.output_text)
curl https://apigw.mka1.com/api/v1/llm/responses \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <mka1-api-key>' \
--header 'X-On-Behalf-Of: <end-user-id>' \
--data '{
"model": "auto",
"instructions": "You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.",
"input": "List my most recent Linear issue assigned to me.",
"store": true,
"stream": false,
"tools": [
{
"type": "mcp",
"server_label": "Linear MCP",
"server_description": "Access Linear issues through MCP.",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": {
"Authorization": "Bearer <linear-api-key>"
},
"require_approval": "never"
}
]
}'
output array contains:
mcp_call— the model’s call to the MCP-discovered toolmcp_call_output— the data returned by the MCP servermessage— the model’s text response summarizing the results
Require end-user approval
Setrequire_approval to 'always' when your app should stop and wait for an approval decision.
In this flow, create the response in background mode, poll it, and look for an mcp_approval_request item in output.
# Step 1: Create a background response with approval required
mka1 llm responses create --body '{
"model": "auto",
"instructions": "You are a project management assistant with access to Linear via MCP.",
"input": "List my most recent Linear issue assigned to me.",
"background": true,
"store": true,
"stream": false,
"tools": [
{
"type": "mcp",
"server_label": "Linear MCP",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": { "Authorization": "Bearer <linear-api-key>" },
"require_approval": "always"
}
]
}'
# Step 2: Poll the response by id until an mcp_approval_request appears
mka1 llm responses get --response-id <response-id>
# Step 3: Send approval to continue
mka1 llm responses create --body '{
"model": "auto",
"previous_response_id": "<response-id>",
"input": [
{
"type": "mcp_approval_response",
"approval_request_id": "<approval-request-id>",
"approve": true
}
],
"store": true,
"stream": false
}'
import { SDK } from '@meetkai/mka1';
import type * as components from '@meetkai/mka1/models/components';
const mka1 = new SDK({
bearerAuth: `Bearer ${YOUR_API_KEY}`,
});
// Step 1: Create a background response with approval required
let pendingResponse = await mka1.llm.responses.create({
xOnBehalfOf: '<end-user-id>',
responsesCreateRequest: {
model: 'auto',
instructions:
'You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.',
input: 'List my most recent Linear issue assigned to me.',
background: true,
store: true,
stream: false,
tools: [
{
type: 'mcp',
serverLabel: 'Linear MCP',
serverDescription: 'Access Linear issues through MCP.',
serverUrl: 'https://mcp.linear.app/mcp',
allowedTools: ['issues.list'],
headers: {
Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
},
requireApproval: 'always',
},
],
},
}) as components.ResponseObject;
// Step 2: Poll until an approval request appears
let approvalRequest: components.MCPApprovalRequest | undefined;
while (
pendingResponse.status === 'queued' ||
pendingResponse.status === 'in_progress'
) {
approvalRequest = pendingResponse.output.find(
(item): item is components.MCPApprovalRequest =>
item.type === 'mcp_approval_request',
);
if (approvalRequest) break;
await new Promise(resolve => setTimeout(resolve, 1000));
pendingResponse = await mka1.llm.responses.get({
responseId: pendingResponse.id,
xOnBehalfOf: '<end-user-id>',
}) as components.ResponseObject;
}
if (!approvalRequest) {
throw new Error(`No approval request found. Response ended with ${pendingResponse.status}.`);
}
// Step 3: Show the user what the model wants to do
console.log('Server:', approvalRequest.serverLabel);
console.log('Tool:', approvalRequest.name);
console.log('Arguments:', approvalRequest.arguments);
// Step 4: Send the approval (or denial) to continue
const approve = true; // Replace with your UI decision
const continuedResponse = await mka1.llm.responses.create({
xOnBehalfOf: '<end-user-id>',
responsesCreateRequest: {
model: 'auto',
previousResponseId: pendingResponse.id,
input: [
{
type: 'mcp_approval_response',
approvalRequestId: approvalRequest.id,
approve,
},
],
store: true,
stream: false,
},
}) as components.ResponseObject;
const assistantText = continuedResponse.output
.filter(
(item): item is components.OutputMessage =>
item.type === 'message' && item.role === 'assistant',
)
.flatMap(item =>
item.content.flatMap(content =>
content.type === 'output_text' ? [content.text] : [],
),
)
.join('\n\n')
.trim();
console.log(assistantText);
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: '<mka1-api-key>',
baseURL: 'https://apigw.mka1.com/api/v1/llm/',
defaultHeaders: { 'X-On-Behalf-Of': '<end-user-id>' },
});
// Step 1: Create a background response with approval required
let pendingResponse = await openai.responses.create({
model: 'auto',
instructions:
'You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.',
input: 'List my most recent Linear issue assigned to me.',
background: true,
store: true,
stream: false,
tools: [
{
type: 'mcp',
server_label: 'Linear MCP',
server_description: 'Access Linear issues through MCP.',
server_url: 'https://mcp.linear.app/mcp',
allowed_tools: ['issues.list'],
headers: {
Authorization: `Bearer ${process.env.LINEAR_API_KEY}`,
},
require_approval: 'always',
},
],
});
// Step 2: Poll until an approval request appears
let approvalRequest;
while (
pendingResponse.status === 'queued' ||
pendingResponse.status === 'in_progress'
) {
approvalRequest = pendingResponse.output.find(
(item) => item.type === 'mcp_approval_request',
);
if (approvalRequest) break;
await new Promise(resolve => setTimeout(resolve, 1000));
pendingResponse = await openai.responses.retrieve(pendingResponse.id);
}
if (!approvalRequest) {
throw new Error(`No approval request found. Response ended with ${pendingResponse.status}.`);
}
// Step 3: Show the user what the model wants to do
console.log('Server:', approvalRequest.server_label);
console.log('Tool:', approvalRequest.name);
console.log('Arguments:', approvalRequest.arguments);
// Step 4: Send the approval (or denial) to continue
const approve = true; // Replace with your UI decision
const continuedResponse = await openai.responses.create({
model: 'auto',
previous_response_id: pendingResponse.id,
input: [
{
type: 'mcp_approval_response',
approval_request_id: approvalRequest.id,
approve,
},
],
store: true,
stream: false,
});
console.log(continuedResponse.output_text);
using MeetKai.MKA1;
using MeetKai.MKA1.Types.Components;
var sdk = new SDK(
bearerAuth: "Bearer <mka1-api-key>",
serverUrl: "https://apigw.mka1.com"
);
// MCP approval workflow requires a running MCP server.
// The SDK can construct background requests with MCP tools.
var request = new ResponsesCreateRequest()
{
Model = "auto",
Input = ResponsesCreateRequestInput.CreateStr("Run the approved tool."),
Background = true,
};
Console.WriteLine(request);
import os
import time
# Step 1: Create a background response with approval required
pending = sdk.llm.responses.create(
model="auto",
instructions="You are a project management assistant with access to Linear via MCP. Use Linear tools when the user asks about tasks, bugs, or projects. Keep the final answer terse.",
input="List my most recent Linear issue assigned to me.",
background=True,
store=True,
stream=False,
tools=[
{
"type": "mcp",
"server_label": "Linear MCP",
"server_description": "Access Linear issues through MCP.",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": {
"Authorization": f"Bearer {os.environ['LINEAR_API_KEY']}",
},
"require_approval": "always",
},
],
)
# Step 2: Poll until an approval request appears
approval_request = None
while pending.status in ("queued", "in_progress"):
for item in pending.output:
if item.type == "mcp_approval_request":
approval_request = item
break
if approval_request:
break
time.sleep(1)
pending = sdk.llm.responses.get(response_id=pending.id)
# Step 3: Show the user what the model wants to do
print("Server:", approval_request.server_label)
print("Tool:", approval_request.name)
print("Arguments:", approval_request.arguments)
# Step 4: Send the approval (or denial) to continue
continued = sdk.llm.responses.create(
model="auto",
previous_response_id=pending.id,
input=[
{
"type": "mcp_approval_response",
"approval_request_id": approval_request.id,
"approve": True,
},
],
store=True,
stream=False,
)
print(continued.output_text)
# Step 1: Create background response with approval required
RESPONSE=$(curl -s https://apigw.mka1.com/api/v1/llm/responses \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <mka1-api-key>' \
--header 'X-On-Behalf-Of: <end-user-id>' \
--data '{
"model": "auto",
"instructions": "You are a project management assistant with access to Linear via MCP.",
"input": "List my most recent Linear issue assigned to me.",
"background": true,
"store": true,
"stream": false,
"tools": [
{
"type": "mcp",
"server_label": "Linear MCP",
"server_url": "https://mcp.linear.app/mcp",
"allowed_tools": ["issues.list"],
"headers": { "Authorization": "Bearer <linear-api-key>" },
"require_approval": "always"
}
]
}')
RESPONSE_ID=$(echo "$RESPONSE" | jq -r '.id')
# Step 2: Poll until approval request appears
while true; do
RESPONSE=$(curl -s "https://apigw.mka1.com/api/v1/llm/responses/$RESPONSE_ID" \
--header 'Authorization: Bearer <mka1-api-key>' \
--header 'X-On-Behalf-Of: <end-user-id>')
APPROVAL_ID=$(echo "$RESPONSE" | jq -r '.output[] | select(.type == "mcp_approval_request") | .id')
if [ -n "$APPROVAL_ID" ] && [ "$APPROVAL_ID" != "null" ]; then break; fi
sleep 1
done
# Step 3: Send approval to continue
curl https://apigw.mka1.com/api/v1/llm/responses \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <mka1-api-key>' \
--header 'X-On-Behalf-Of: <end-user-id>' \
--data "{
\"model\": \"auto\",
\"previous_response_id\": \"$RESPONSE_ID\",
\"input\": [
{
\"type\": \"mcp_approval_response\",
\"approval_request_id\": \"$APPROVAL_ID\",
\"approve\": true
}
],
\"store\": true,
\"stream\": false
}"
approve: false.
You can also include a reason field in the mcp_approval_response item.
For approval UIs, show:
server_label— which MCP server is being usedname— which tool the model wants to callarguments— what arguments it plans to send
MCP tool definition reference
| Parameter | Type | Default | Description |
|---|---|---|---|
type | "mcp" | — | Required. Identifies this as an MCP tool. |
server_label | string | — | Required. Display name for the MCP server. |
server_url | string | — | URL of the MCP server endpoint. |
server_description | string | — | Optional description of the server’s purpose. |
allowed_tools | string[] | — | Limit which tools the model can call. |
headers | object | — | Headers to pass to the MCP server (e.g. auth tokens). |
require_approval | "always" | "never" | "always" | Whether to pause for end-user approval before calling. |
connector_id | string | — | Use a preconfigured connector instead of a custom server URL. |
headers are automatically masked in stored responses and streaming events.
Next steps
- See generate a response for the base Responses flow
- See background responses for polling and streaming patterns
- See conversations if you want to keep the same end user in a longer thread
- Review the API reference for the full Responses schema