Skip to content

Commit 0f52384

Browse files
JakeSCahillcoderabbitai[bot]paulohtb6
authored
Add docs for remote MCP servers (#413)
* Add docs for remote MCP servers * Update modules/ai-agents/pages/mcp/remote/developer-guide.adoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Add period * Apply suggestions from code review * Update modules/ai-agents/pages/mcp/remote/developer-guide.adoc * Update nav * Update nav * Apply suggestions from code review * Simplify * Update configuration.adoc * Update overview.adoc * Update headings to be task oriented * Require 25.2.5 * Improve overview * Improvements * Split examples * Clarify mcp client * Pipeline -> configuation * Use templates for quickstart * Use templates for quickstart * Fix grammar * Update modules/ai-agents/pages/mcp/remote/overview.adoc Co-authored-by: Paulo Borges <[email protected]> * Apply suggestions from code review Co-authored-by: Paulo Borges <[email protected]> * Add lint details * Update whats new * Clarify docs MCP * Document property restrictions * Remove private beta * Remove private beta * Fix formatting --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Paulo Borges <[email protected]>
1 parent b02bde2 commit 0f52384

29 files changed

+1567
-29
lines changed

modules/ROOT/nav.adoc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,18 @@
6969
** xref:security:secrets.adoc[Secrets]
7070
** xref:security:cloud-safety-reliability.adoc[Safety and Reliability]
7171
72-
* xref:ai-agents:mcp/local/index.adoc[]
73-
** xref:ai-agents:mcp/local/overview.adoc[Overview]
74-
** xref:ai-agents:mcp/local/quickstart.adoc[Quickstart]
75-
** xref:ai-agents:mcp/local/configuration.adoc[Configure]
72+
* xref:ai-agents:index.adoc[AI Agents]
73+
** xref:ai-agents:mcp/overview.adoc[MCP Overview]
74+
** xref:ai-agents:mcp/local/index.adoc[Local Redpanda Cloud MCP]
75+
*** xref:ai-agents:mcp/local/overview.adoc[Overview]
76+
*** xref:ai-agents:mcp/local/quickstart.adoc[Quickstart]
77+
*** xref:ai-agents:mcp/local/configuration.adoc[Configure]
78+
** xref:ai-agents:mcp/remote/index.adoc[Remote MCP]
79+
*** xref:ai-agents:mcp/remote/overview.adoc[Overview]
80+
*** xref:ai-agents:mcp/remote/quickstart.adoc[Quickstart]
81+
*** xref:ai-agents:mcp/remote/developer-guide.adoc[Developer Guide]
82+
*** xref:ai-agents:mcp/remote/admin-guide.adoc[Admin Guide]
83+
*** xref:ai-agents:mcp/remote/pipeline-patterns.adoc[MCP Server Patterns]
7684
7785
* xref:develop:connect/about.adoc[Redpanda Connect]
7886
** xref:develop:connect/connect-quickstart.adoc[Quickstart]
@@ -490,8 +498,9 @@
490498
***** xref:reference:rpk/rpk-cloud/rpk-cloud-cluster-select.adoc[]
491499
**** xref:reference:rpk/rpk-cloud/rpk-cloud-login.adoc[]
492500
**** xref:reference:rpk/rpk-cloud/rpk-cloud-logout.adoc[]
493-
**** rpk cloud mcp
501+
**** xref:reference:rpk/rpk-cloud/rpk-cloud-mcp.adoc[]
494502
***** xref:reference:rpk/rpk-cloud/rpk-cloud-mcp-install.adoc[]
503+
***** xref:reference:rpk/rpk-cloud/rpk-cloud-mcp-proxy.adoc[]
495504
***** xref:reference:rpk/rpk-cloud/rpk-cloud-mcp-stdio.adoc[]
496505
*** xref:reference:rpk/rpk-cluster/rpk-cluster.adoc[]
497506
**** xref:reference:rpk/rpk-cluster/rpk-cluster-config.adoc[]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
label: customer_enrichment
2+
processors:
3+
- label: fetch_customer_base
4+
sql_select:
5+
driver: "postgres"
6+
dsn: "${secrets.POSTGRES_DSN}"
7+
table: "customers"
8+
where: "customer_id = ?"
9+
args_mapping: 'root = [this.customer_id]'
10+
11+
- label: enrich_with_orders
12+
sql_select:
13+
driver: "postgres"
14+
dsn: "${secrets.POSTGRES_DSN}"
15+
table: "orders"
16+
where: "customer_id = ? AND created_at >= NOW() - INTERVAL '30 days'"
17+
args_mapping: 'root = [this.customer_id]'
18+
19+
- label: combine_data
20+
mutation: |
21+
root = {
22+
"customer": this.customers.index(0),
23+
"recent_orders": this.orders,
24+
"metrics": {
25+
"total_orders": this.orders.length(),
26+
"total_spent": this.orders.map_each(o -> o.total).sum(),
27+
"avg_order_value": this.orders.map_each(o -> o.total).mean()
28+
}
29+
}
30+
31+
meta:
32+
mcp:
33+
enabled: true
34+
description: "Get comprehensive customer profile with recent order history and metrics"
35+
properties:
36+
- name: customer_id
37+
type: string
38+
description: "Customer ID to analyze"
39+
required: true
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
label: gcp_bigquery_select_processor
2+
processors:
3+
- label: prepare_parameters
4+
mutation: |
5+
meta customer_id = this.customer_id.string().catch("12345")
6+
meta limit = this.limit.number().catch(10)
7+
- label: query_bigquery
8+
gcp_bigquery_select:
9+
project: my-gcp-project
10+
credentials_json: |
11+
${secrets.BIGQUERY_CREDENTIALS}
12+
table: my_dataset.customer_orders
13+
columns:
14+
- "order_id"
15+
- "customer_id"
16+
- "order_date"
17+
- "total_amount"
18+
- "status"
19+
where: customer_id = ? AND order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
20+
suffix: "ORDER BY order_date DESC LIMIT ?"
21+
args_mapping: root = [ @customer_id, @limit ]
22+
- label: format_response
23+
mutation: |
24+
root = {
25+
"orders": this,
26+
"metadata": {
27+
"source": "BigQuery",
28+
"customer_id": @customer_id,
29+
"fetched_at": now().ts_format("2006-01-02T15:04:05.000Z")
30+
}
31+
}
32+
33+
meta:
34+
mcp:
35+
enabled: true
36+
description: "Query customer orders from BigQuery"
37+
properties:
38+
- name: customer_id
39+
type: string
40+
description: "Customer ID to filter orders"
41+
required: true
42+
- name: limit
43+
type: number
44+
description: "Maximum number of orders to return"
45+
required: false
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
label: generate_input
2+
generate:
3+
mapping: |
4+
let event_type = ["login", "logout", "purchase", "view_page", "click_button"].index(random_int(max:4))
5+
root = {
6+
"id": uuid_v4(),
7+
"timestamp": now().ts_format("2006-01-02T15:04:05.000Z"),
8+
"user_id": random_int(min:1, max:10000),
9+
"event_type": $event_type,
10+
"data": {
11+
"session_id": ksuid(),
12+
"ip_address": "192.168.%v.%v".format(random_int(max:255), random_int(min:1, max:254)),
13+
"user_agent": ["Chrome", "Firefox", "Safari", "Edge"].index(random_int(max:3)),
14+
"amount": if $event_type == "purchase" { random_int(min:10, max:500) } else { null }
15+
}
16+
}
17+
18+
meta:
19+
mcp:
20+
enabled: true
21+
description: "Generate an example user event message with realistic data"
22+
properties: []
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
label: fetch-weather
2+
processors:
3+
- label: prepare_parameters
4+
mutation: |
5+
meta city_name = this.city_name
6+
- label: fetch_weather
7+
http:
8+
url: 'https://wttr.in/${! @city_name }?format=j1'
9+
verb: GET
10+
headers:
11+
Accept: "application/json"
12+
User-Agent: "redpanda-mcp-server/1.0"
13+
- label: format_response
14+
mutation: |
15+
root = {
16+
"city": @city_name,
17+
"temperature": this.current_condition.0.temp_C.number(),
18+
"feels_like": this.current_condition.0.FeelsLikeC.number(),
19+
"humidity": this.current_condition.0.humidity.number(),
20+
"pressure": this.current_condition.0.pressure.number(),
21+
"description": this.current_condition.0.weatherDesc.0.value,
22+
"wind_speed": this.current_condition.0.windspeedKmph.number(),
23+
"metadata": {
24+
"source": "wttr.in",
25+
"fetched_at": now().ts_format("2006-01-02T15:04:05.000Z")
26+
}
27+
}
28+
29+
meta:
30+
mcp:
31+
enabled: true
32+
description: "Fetch current weather information for a specified city"
33+
properties:
34+
- name: city_name
35+
type: string
36+
description: "Name of the city to get weather information for"
37+
required: true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
label: memory_cache
2+
memory:
3+
default_ttl: "5m"
4+
init_values:
5+
"user:1001": '{"name": "Alice", "role": "admin"}'
6+
"user:1002": '{"name": "Bob", "role": "user"}'
7+
"config:theme": "dark"
8+
"config:language": "en"
9+
shards: 4
10+
11+
meta:
12+
mcp:
13+
enabled: true
14+
description: "In-memory cache for storing user data, configuration, and temporary values"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
label: observable_tool
2+
processors:
3+
- label: init_tracing
4+
mutation: |
5+
# Generate correlation ID for request tracing
6+
meta req_id = uuid_v7()
7+
meta start_time = now()
8+
9+
# Log request start with structured data
10+
root.trace = {
11+
"request_id": @req_id,
12+
"timestamp": @start_time.ts_format("2006-01-02T15:04:05.000Z"),
13+
"tool": "observable_tool",
14+
"version": "1.0.0"
15+
}
16+
17+
- label: log_request_start
18+
log:
19+
message: "MCP tool request started"
20+
fields:
21+
request_id: "${! @req_id }"
22+
tool_name: "observable_tool"
23+
input_params: "${! this.without(\"trace\") }"
24+
user_agent: "${! meta(\"User-Agent\").catch(\"unknown\") }"
25+
level: "INFO"
26+
27+
- label: finalize_response
28+
mutation: |
29+
# Calculate total execution time
30+
meta duration = (now().ts_unix_nano() - @start_time.ts_unix_nano()) / 1000000
31+
32+
# Add trace information to response
33+
root.metadata = {
34+
"request_id": @req_id,
35+
"execution_time_ms": @duration,
36+
"timestamp": now().ts_format("2006-01-02T15:04:05.000Z"),
37+
"tool": "observable_tool",
38+
"success": !this.exists("error")
39+
}
40+
41+
- label: log_completion
42+
log:
43+
message: "MCP tool request completed"
44+
fields:
45+
request_id: "${! @req_id }"
46+
duration_ms: "${! this.metadata.execution_time_ms }"
47+
success: "${! this.metadata.success }"
48+
result_size: "${! content().length() }"
49+
level: "INFO"
50+
51+
meta:
52+
tags: [ example ]
53+
mcp:
54+
enabled: true
55+
description: "Example tool with comprehensive observability and error handling"
56+
properties:
57+
- name: user_id
58+
type: string
59+
description: "User ID to fetch data for"
60+
required: true
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
label: order_workflow
2+
processors:
3+
- label: validate_order
4+
mutation: |
5+
# Validation logic
6+
root = if this.total <= 0 {
7+
throw("Invalid order total")
8+
} else { this }
9+
10+
- label: mock_inventory_check
11+
mutation: |
12+
# Mock inventory data for testing
13+
let inventory = {
14+
"widget-001": {"quantity": 100, "name": "Standard Widget"},
15+
"widget-premium": {"quantity": 25, "name": "Premium Widget"},
16+
"widget-limited": {"quantity": 2, "name": "Limited Edition Widget"}
17+
}
18+
19+
let product = $inventory.get(this.product_id)
20+
root = if $product == null {
21+
throw("Product not found: " + this.product_id)
22+
} else if $product.quantity < this.quantity {
23+
throw("Insufficient inventory. Available: " + $product.quantity.string())
24+
} else {
25+
this.merge({
26+
"inventory_check": "passed",
27+
"available_quantity": $product.quantity,
28+
"product_name": $product.name
29+
})
30+
}
31+
32+
- label: route_by_priority
33+
switch:
34+
- check: 'this.total > 1000'
35+
processors:
36+
- label: mock_high_value_processing
37+
mutation: |
38+
# Mock premium processing
39+
root = this.merge({
40+
"processing_tier": "premium",
41+
"processing_time_estimate": "2-4 hours",
42+
"assigned_rep": "[email protected]",
43+
"priority_score": 95
44+
})
45+
46+
- check: 'this.customer_tier == "vip"'
47+
processors:
48+
- label: mock_vip_processing
49+
mutation: |
50+
# Mock VIP processing
51+
root = this.merge({
52+
"processing_tier": "vip",
53+
"processing_time_estimate": "1-2 hours",
54+
"assigned_rep": "[email protected]",
55+
"priority_score": 90,
56+
"perks": ["expedited_shipping", "white_glove_service"]
57+
})
58+
59+
- processors:
60+
- label: mock_standard_processing
61+
mutation: |
62+
# Mock standard processing
63+
root = this.merge({
64+
"processing_tier": "standard",
65+
"processing_time_estimate": "24-48 hours",
66+
"assigned_rep": "[email protected]",
67+
"priority_score": 50
68+
})
69+
70+
- label: finalize_order
71+
mutation: |
72+
# Add final processing metadata
73+
# Calculate estimated fulfillment by parsing processing time
74+
let max_hours = this.processing_time_estimate.split("-").index(1).split(" ").index(0).number()
75+
76+
root = this.merge({
77+
"order_status": "processed",
78+
"processed_at": now().ts_format("2006-01-02T15:04:05.000Z"),
79+
"estimated_fulfillment": "TBD - calculated based on processing tier",
80+
"processing_time_hours": $max_hours
81+
})
82+
83+
meta:
84+
mcp:
85+
enabled: true
86+
description: "Process orders with validation, inventory check, and tiered routing (with mocks for testing)"
87+
properties:
88+
- name: order_id
89+
type: string
90+
description: "Unique order identifier"
91+
required: true
92+
- name: product_id
93+
type: string
94+
description: "Product ID (try: widget-001, widget-premium, widget-limited)"
95+
required: true
96+
- name: quantity
97+
type: number
98+
description: "Quantity to order"
99+
required: true
100+
- name: total
101+
type: number
102+
description: "Order total in dollars"
103+
required: true
104+
- name: customer_tier
105+
type: string
106+
description: "Customer tier (optional: vip, standard)"
107+
required: false
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
label: redpanda_cache
2+
redpanda:
3+
seed_brokers: ["${REDPANDA_BROKERS}"]
4+
topic: "mcp-cache-topic"
5+
tls:
6+
enabled: true
7+
sasl:
8+
- mechanism: "SCRAM-SHA-512"
9+
username: "${secrets.MCP_REDPANDA_CREDENTIALS.username}"
10+
password: "${secrets.MCP_REDPANDA_CREDENTIALS.password}"
11+
12+
meta:
13+
mcp:
14+
enabled: true
15+
description: "Redpanda-backed distributed cache using Kafka topics for persistence"

0 commit comments

Comments
 (0)