Skip to content

Commit 1f0b186

Browse files
jasoncabotMaximo-Guk
authored andcommitted
Renamed to logpush and updated local dev handling of token
1 parent 541fc90 commit 1f0b186

File tree

7 files changed

+127
-90
lines changed

7 files changed

+127
-90
lines changed

apps/logpush/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "logs",
2+
"name": "logpush",
33
"version": "0.0.1",
44
"private": true,
55
"scripts": {

apps/logpush/src/tools/context.ts renamed to apps/logpush/src/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ export interface Env {
1212
MCP_OBJECT: DurableObjectNamespace<LogsMCP>
1313
USER_DETAILS: DurableObjectNamespace<UserDetails>
1414
MCP_METRICS: AnalyticsEngineDataset
15-
}
15+
}

apps/logpush/src/index.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@ import {
88
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
99
import { getEnv } from '@repo/mcp-common/src/env'
1010
import { RequiredScopes } from '@repo/mcp-common/src/scopes'
11-
import { initSentryWithUser } from '@repo/mcp-common/src/sentry'
1211
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'
1312
import { registerAccountTools } from '@repo/mcp-common/src/tools/account'
1413

1514
import { MetricsTracker } from '../../../packages/mcp-observability/src'
1615
import { registerLogsTools } from './tools/logs'
1716

1817
import type { AccountSchema, UserSchema } from '@repo/mcp-common/src/cloudflare-oauth-handler'
19-
2018
import type { Env } from './context'
2119

22-
export { UserDetails }
23-
2420
const env = getEnv<Env>()
2521

22+
export { UserDetails }
23+
2624
const metrics = new MetricsTracker(env.MCP_METRICS, {
2725
name: env.MCP_SERVER_NAME,
2826
version: env.MCP_SERVER_VERSION,
@@ -64,15 +62,12 @@ export class LogsMCP extends McpAgent<Env, State, Props> {
6462
name: this.env.MCP_SERVER_NAME,
6563
version: this.env.MCP_SERVER_VERSION,
6664
},
67-
sentry: initSentryWithUser(env, this.ctx, this.props.user.id),
6865
})
6966

70-
this.props.apiToken = env.CLOUDFLARE_ACCESS_TOKEN
71-
7267
registerAccountTools(this)
7368

74-
// Register Cloudflare Workers logs tools
75-
registerLogsTools(this)
69+
// Register Cloudflare Log Push tools
70+
registerLogsTools(this, env.CLOUDFLARE_ACCESS_TOKEN)
7671
}
7772

7873
async getActiveAccountId() {
@@ -97,17 +92,18 @@ export class LogsMCP extends McpAgent<Env, State, Props> {
9792
}
9893
}
9994

100-
const ObservabilityScopes = {
95+
const LogPushScopes = {
10196
...RequiredScopes,
10297
'account:read': 'See your account info such as account details, analytics, and memberships.',
103-
'logpush:write': 'Grants read and write access to Logpull and Logpush, and read access to Instant Logs. Note that all Logpush API operations require Logs: Write permission because Logpush jobs contain sensitive information.',
98+
'logpush:write':
99+
'Grants read and write access to Logpull and Logpush, and read access to Instant Logs. Note that all Logpush API operations require Logs: Write permission because Logpush jobs contain sensitive information.',
104100
} as const
105101

106102
export default new OAuthProvider({
107103
apiRoute: '/sse',
108104
apiHandler: LogsMCP.mount('/sse'),
109105
// @ts-ignore
110-
defaultHandler: createAuthHandlers({ scopes: ObservabilityScopes, metrics }),
106+
defaultHandler: createAuthHandlers({ scopes: LogPushScopes, metrics }),
111107
authorizeEndpoint: '/oauth/authorize',
112108
tokenEndpoint: '/token',
113109
tokenExchangeCallback: (options) =>

apps/logpush/src/tools/logs.ts

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,67 @@
11
import { z } from 'zod'
22

33
import { fetchCloudflareApi } from '@repo/mcp-common/src/cloudflare-api'
4+
45
import type { LogsMCP } from '../index'
56

6-
const zJobIdentifier = z.number().int().min(1).optional().describe("Unique id of the job.");
7-
const zEnabled = z.boolean().optional().describe("Flag that indicates if the job is enabled.");
8-
const zName = z.string()
9-
.regex(/^[a-zA-Z0-9\-\.]*$/)
10-
.max(512)
11-
.nullable()
12-
.optional()
13-
.describe("Optional human readable job name. Not unique.");
14-
const zDataset = z.string()
15-
.regex(/^[a-zA-Z0-9_\-]*$/)
16-
.max(256)
17-
.nullable()
18-
.optional()
19-
.describe("Name of the dataset.");
20-
const zLastComplete = z.string()
21-
.datetime()
22-
.nullable()
23-
.optional()
24-
.describe("Records the last time for which logs have been successfully pushed.");
25-
const zLastError = z.string()
26-
.datetime()
27-
.nullable()
28-
.optional()
29-
.describe("Records the last time the job failed.");
30-
const zErrorMessage = z.string()
31-
.nullable()
32-
.optional()
33-
.describe("If not null, the job is currently failing.");
7+
const zJobIdentifier = z.number().int().min(1).optional().describe('Unique id of the job.')
8+
const zEnabled = z.boolean().optional().describe('Flag that indicates if the job is enabled.')
9+
const zName = z
10+
.string()
11+
.regex(/^[a-zA-Z0-9\-\.]*$/)
12+
.max(512)
13+
.nullable()
14+
.optional()
15+
.describe('Optional human readable job name. Not unique.')
16+
const zDataset = z
17+
.string()
18+
.regex(/^[a-zA-Z0-9_\-]*$/)
19+
.max(256)
20+
.nullable()
21+
.optional()
22+
.describe('Name of the dataset.')
23+
const zLastComplete = z
24+
.string()
25+
.datetime()
26+
.nullable()
27+
.optional()
28+
.describe('Records the last time for which logs have been successfully pushed.')
29+
const zLastError = z
30+
.string()
31+
.datetime()
32+
.nullable()
33+
.optional()
34+
.describe('Records the last time the job failed.')
35+
const zErrorMessage = z
36+
.string()
37+
.nullable()
38+
.optional()
39+
.describe('If not null, the job is currently failing.')
40+
41+
export const zLogpushJob = z
42+
.object({
43+
id: zJobIdentifier,
44+
enabled: zEnabled,
45+
name: zName,
46+
dataset: zDataset,
47+
last_complete: zLastComplete,
48+
last_error: zLastError,
49+
error_message: zErrorMessage,
50+
})
51+
.nullable()
52+
.optional()
3453

35-
export const zLogpushJob = z.object({
36-
id: zJobIdentifier,
37-
enabled: zEnabled,
38-
name: zName,
39-
dataset: zDataset,
40-
last_complete: zLastComplete,
41-
last_error: zLastError,
42-
error_message: zErrorMessage,
43-
}).nullable().optional();
44-
45-
const zApiResponseCommon = z.object({
54+
const zApiResponseCommon = z.object({
4655
success: z.literal(true),
47-
errors: z.array(z.object({ message: z.string() })).optional()
48-
});
56+
errors: z.array(z.object({ message: z.string() })).optional(),
57+
})
4958

5059
const zLogPushJobResults = z.array(zLogpushJob).optional()
51-
52-
// The complete schema for zone_logpush_job_response_collection
60+
61+
// The complete schema for zone_logpush_job_response_collection
5362
export const zLogpushJobResponseCollection = zApiResponseCommon.extend({
54-
result: zLogPushJobResults
55-
});
63+
result: zLogPushJobResults,
64+
})
5665

5766
/**
5867
* Fetches available telemetry keys for a specified Cloudflare Worker
@@ -63,7 +72,7 @@ export const zLogpushJobResponseCollection = zApiResponseCommon.extend({
6372

6473
export async function handleGetAccountLogPushJobs(
6574
accountId: string,
66-
apiToken: string,
75+
apiToken: string
6776
): Promise<z.infer<typeof zLogPushJobResults>> {
6877
// Call the Public API
6978
const data = await fetchCloudflareApi({
@@ -81,17 +90,16 @@ export async function handleGetAccountLogPushJobs(
8190
})
8291

8392
const res = data as z.infer<typeof zLogpushJobResponseCollection>
84-
return (res.result.slice(0, 100) || [])
93+
return res.result?.slice(0, 100) || []
8594
}
8695

87-
8896
/**
8997
* Registers the logs analysis tool with the MCP server
9098
* @param server The MCP server instance
9199
* @param accountId Cloudflare account ID
92100
* @param apiToken Cloudflare API token
93101
*/
94-
export function registerLogsTools(agent: LogsMCP) {
102+
export function registerLogsTools(agent: LogsMCP, devToken: string) {
95103
// Register the worker logs analysis tool by worker name
96104
agent.server.tool(
97105
'logpush_jobs_by_account_id',
@@ -117,8 +125,8 @@ export function registerLogsTools(agent: LogsMCP) {
117125
}
118126
}
119127
try {
120-
const token = agent.props.apiToken.length > 0 ? agent.props.apiToken : agent.props.accessToken
121-
const result = await handleGetAccountLogPushJobs(accountId, token)
128+
const token = devToken.length > 0 ? devToken : agent.props.accessToken
129+
const result = await handleGetAccountLogPushJobs(accountId, token)
122130
return {
123131
content: [
124132
{

apps/logpush/worker-configuration.d.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,4 @@
1-
// Generated by Wrangler by running `wrangler types` (hash: a6731bb9abcd7bac3335343600366a9e)
21
// Runtime types generated with [email protected] 2025-03-10 nodejs_compat
3-
declare namespace Cloudflare {
4-
interface Env {
5-
OAUTH_KV: KVNamespace;
6-
ENVIRONMENT: "development" | "staging" | "production";
7-
MCP_SERVER_NAME: "PLACEHOLDER" | "logs-staging" | "logs";
8-
MCP_SERVER_VERSION: "PLACEHOLDER" | "1.0.0";
9-
CLOUDFLARE_CLIENT_ID: string;
10-
CLOUDFLARE_CLIENT_SECRET: string;
11-
CLOUDFLARE_ACCESS_TOKEN: string;
12-
MCP_OBJECT: DurableObjectNamespace<import("./src/index").LogsMCP>;
13-
MCP_METRICS: AnalyticsEngineDataset;
14-
}
15-
}
16-
interface Env extends Cloudflare.Env {}
17-
182
// Begin runtime types
193
/*! *****************************************************************************
204
Copyright (c) Cloudflare. All rights reserved.

apps/logpush/wrangler.jsonc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"main": "src/index.ts",
88
"compatibility_date": "2025-03-10",
99
"compatibility_flags": ["nodejs_compat"],
10-
"name": "mcp-cloudflare-logs-dev",
10+
"name": "mcp-cloudflare-logpush-dev",
1111
"migrations": [
1212
{
1313
"new_sqlite_classes": ["UserDetails", "LogsMCP"],
@@ -55,7 +55,7 @@
5555
],
5656
"env": {
5757
"staging": {
58-
"name": "mcp-cloudflare-logs-staging",
58+
"name": "mcp-cloudflare-logpush-staging",
5959
"account_id": "6702657b6aa048cf3081ff3ff3c9c52f",
6060
"routes": [{ "pattern": "logs-staging.mcp.cloudflare.com", "custom_domain": true }],
6161
"durable_objects": {
@@ -72,13 +72,13 @@
7272
},
7373
"kv_namespaces": [
7474
{
75-
"binding": "OAUTH_KV_LOGS_STAGING",
76-
"id": "a6ad24203a244d248f2fe1acfeb7b3a3"
75+
"binding": "OAUTH_KV_LOGPUSH_STAGING",
76+
"id": "3804747ed31344cca8e4ebecd255e417"
7777
}
7878
],
7979
"vars": {
8080
"ENVIRONMENT": "staging",
81-
"MCP_SERVER_NAME": "logs-staging",
81+
"MCP_SERVER_NAME": "logpush-staging",
8282
"MCP_SERVER_VERSION": "1.0.0"
8383
},
8484
"analytics_engine_datasets": [
@@ -89,7 +89,7 @@
8989
]
9090
},
9191
"production": {
92-
"name": "mcp-cloudflare-logs-production",
92+
"name": "mcp-cloudflare-logpush-production",
9393
"account_id": "6702657b6aa048cf3081ff3ff3c9c52f",
9494
"routes": [{ "pattern": "logs.mcp.cloudflare.com", "custom_domain": true }],
9595
"durable_objects": {
@@ -106,13 +106,13 @@
106106
},
107107
"kv_namespaces": [
108108
{
109-
"binding": "OAUTH_KV_LOGS_PRODUCTION",
110-
"id": "753f27a19ef94d7dbd49de05588ca890"
109+
"binding": "OAUTH_KV_LOGPUSH_PRODUCTION",
110+
"id": "400ff7a67c824f9698f9e5c25bf51a1c"
111111
}
112112
],
113113
"vars": {
114114
"ENVIRONMENT": "production",
115-
"MCP_SERVER_NAME": "logs",
115+
"MCP_SERVER_NAME": "logpush",
116116
"MCP_SERVER_VERSION": "1.0.0"
117117
},
118118
"analytics_engine_datasets": [

pnpm-lock.yaml

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)