Skip to content

Commit 4b5533c

Browse files
author
flowcore-platform
committed
fix(package): 🎨 Update entry point and restructure CLI implementation
1 parent 53d073b commit 4b5533c

File tree

3 files changed

+160
-217
lines changed

3 files changed

+160
-217
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
"type": "module",
77
"main": "dist/index.js",
88
"bin": {
9-
"platform-mcp-server": "./dist/cli.js"
9+
"platform-mcp-server": "./dist/index.js"
1010
},
1111
"files": [
1212
"dist",
13+
"package.json",
1314
"README.md"
1415
],
1516
"scripts": {
16-
"build": "bun build ./src/cli.ts --outdir ./dist --target node",
17+
"build": "bun build ./src/index.ts --outdir ./dist --target node",
1718
"prepublishOnly": "bun run build",
1819
"inspect": "bunx @modelcontextprotocol/inspector bun src/index.ts",
1920
"lint": "biome lint",

src/cli.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/index.ts

Lines changed: 157 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,210 +1,159 @@
1-
import { FlowcoreClient } from "@flowcore/sdk";
2-
import { OidcClient } from "@flowcore/sdk-oidc-client";
1+
import { FlowcoreClient } from "@flowcore/sdk"
2+
import { OidcClient } from "@flowcore/sdk-oidc-client"
3+
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"
4+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
5+
import { parseArgs } from "node:util"
6+
import { z } from "zod"
7+
import { dataCoreResource, eventTypeResource, flowTypeResource, tenantResource } from "./resources"
38
import {
4-
McpServer,
5-
ResourceTemplate,
6-
} from "@modelcontextprotocol/sdk/server/mcp.js";
7-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8-
import { parseArgs } from "node:util";
9-
import { z } from "zod";
10-
import {
11-
dataCoreResource,
12-
eventTypeResource,
13-
flowTypeResource,
14-
tenantResource,
15-
} from "./resources";
16-
import {
17-
getEventTypeInfoHandler,
18-
getEventsHandler,
19-
getTimeBucketsHandler,
20-
listDataCoresHandler,
21-
listEventTypesHandler,
22-
listFlowTypesHandler,
23-
listTenantsHandler,
24-
} from "./tools";
25-
26-
const OIDC_ISSUER =
27-
"https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration";
28-
29-
export async function startServer() {
30-
// Parse command line arguments
31-
const { values, positionals } = parseArgs({
32-
args: process.argv.slice(2),
33-
options: {
34-
serviceAccountId: { type: "string" },
35-
serviceAccountKey: { type: "string" },
36-
},
37-
allowPositionals: true,
38-
});
39-
40-
// Log positional arguments if any (for debugging)
41-
if (positionals.length > 0) {
42-
console.warn(
43-
`Warning: Unexpected positional arguments: ${positionals.join(", ")}`,
44-
);
45-
}
46-
47-
const serviceAccountId = values.serviceAccountId as string;
48-
const serviceAccountKey = values.serviceAccountKey as string;
49-
50-
if (!serviceAccountId || !serviceAccountKey) {
51-
console.error("Error: No service account credentials provided");
52-
console.error(
53-
"Usage: npx @flowcore/platform-mcp-server --serviceAccountId <accountid> --serviceAccountKey <key>",
54-
);
55-
process.exit(1);
56-
}
57-
58-
const oidcClient = new OidcClient(
59-
serviceAccountId,
60-
serviceAccountKey,
61-
OIDC_ISSUER,
62-
);
63-
const flowcoreClient = new FlowcoreClient({
64-
getBearerToken: async () => {
65-
const token = await oidcClient.getToken();
66-
return token.accessToken;
67-
},
68-
});
69-
70-
const server = new McpServer({
71-
name: "Flowcore Platform",
72-
version: "1.0.0",
73-
description:
74-
"An MCP server for managing and interacting with Flowcore Platform. For information on the details of the flowcore platform, you can check the Flowcore Platform Data Core, as it houses all actions that have happened in the platform. These actions are called events and are the main building blocks of the platform and housed within the data core inside the event type. The hirearchy of the platform is as follows: Users -> Tenant -> Data Core -> Flow Type -> Event Type -> Events. Tenants and organizations are the same thing in the platform, we are transitioning to use the term tenant. The events are stored in time buckets, and can be fetched by using the get_time_buckets tool.",
75-
});
76-
77-
server.tool(
78-
"list_tenants",
79-
"List all tenants I have access to",
80-
listTenantsHandler(flowcoreClient),
81-
);
82-
server.tool(
83-
"list_data_cores",
84-
"List all data cores for a tenant",
85-
{ tenantId: z.string().describe("The tenant ID to list data cores for") },
86-
listDataCoresHandler(flowcoreClient),
87-
);
88-
89-
server.tool(
90-
"list_flow_types",
91-
"List all flow types for a data core",
92-
{
93-
dataCoreId: z
94-
.string()
95-
.describe("The data core ID to list flow types for"),
96-
},
97-
listFlowTypesHandler(flowcoreClient),
98-
);
99-
100-
server.tool(
101-
"list_event_types",
102-
"List all event types for a flow type",
103-
{
104-
flowTypeId: z
105-
.string()
106-
.describe("The flow type ID to list event types for"),
107-
},
108-
listEventTypesHandler(flowcoreClient),
109-
);
110-
111-
server.tool(
112-
"get_event_type_info",
113-
"Get event information about an event type, like first and last time bucket and 5 example events",
114-
{
115-
eventTypeId: z
116-
.string()
117-
.describe("The event type ID to get information for"),
118-
},
119-
getEventTypeInfoHandler(flowcoreClient),
120-
);
121-
122-
server.tool(
123-
"get_events",
124-
"Get events for an event type, this can be paginated by using the cursor returned from the previous call. This is good for getting the payload of the events to inspect them.",
125-
{
126-
eventTypeId: z.string().describe("The event type ID to get events for"),
127-
timeBucket: z
128-
.string()
129-
.describe(
130-
"The time bucket to get events from, the timebucket is in the format of YYYYMMDDhhiiss, normally the ii and ss are 0000",
131-
),
132-
cursor: z
133-
.string()
134-
.optional()
135-
.describe("The paging cursor for pagination"),
136-
pageSize: z
137-
.number()
138-
.optional()
139-
.describe("The number of events per page (default is 10,000)"),
140-
fromEventId: z.string().optional().describe("Start from this event ID"),
141-
afterEventId: z
142-
.string()
143-
.optional()
144-
.describe(
145-
"Get events after this event ID (not applicable if fromEventId is defined)",
146-
),
147-
toEventId: z.string().optional().describe("End at this event ID"),
148-
order: z
149-
.enum(["asc", "desc"])
150-
.optional()
151-
.describe(
152-
"The order of events (asc or desc). When using desc, pagination and filters are not possible",
153-
),
154-
},
155-
getEventsHandler(flowcoreClient),
156-
);
157-
158-
server.tool(
159-
"get_time_buckets",
160-
"Get time buckets for an event type, this is useful for getting the time buckets for an event type, and then using the get_events tool to get the events for a specific time bucket. The time bucket is in the format of YYYYMMDDhhiiss, normally the ii and ss are 0000. It can be paginated by using the cursor returned from the previous call.",
161-
{
162-
eventTypeId: z
163-
.string()
164-
.describe("The event type ID to get time buckets for"),
165-
fromTimeBucket: z
166-
.string()
167-
.optional()
168-
.describe("Start from this time bucket"),
169-
toTimeBucket: z.string().optional().describe("End at this time bucket"),
170-
pageSize: z
171-
.number()
172-
.optional()
173-
.describe("Number of time buckets per page"),
174-
cursor: z.number().optional().describe("Pagination cursor"),
175-
order: z
176-
.enum(["asc", "desc"])
177-
.optional()
178-
.describe("Sort order (asc or desc)"),
179-
},
180-
getTimeBucketsHandler(flowcoreClient),
181-
);
182-
183-
server.resource(
184-
"tenant",
185-
new ResourceTemplate("tenant://{tenantId}", { list: undefined }),
186-
tenantResource(flowcoreClient),
187-
);
188-
189-
server.resource(
190-
"data_core",
191-
new ResourceTemplate("data-core://{dataCoreId}", { list: undefined }),
192-
dataCoreResource(flowcoreClient),
193-
);
194-
195-
server.resource(
196-
"flow_type",
197-
new ResourceTemplate("flow-type://{flowTypeId}", { list: undefined }),
198-
flowTypeResource(flowcoreClient),
199-
);
200-
201-
server.resource(
202-
"event_type",
203-
new ResourceTemplate("event-type://{eventTypeId}", { list: undefined }),
204-
eventTypeResource(flowcoreClient),
205-
);
206-
207-
// Start receiving messages on stdin and sending messages on stdout
208-
const transport = new StdioServerTransport();
209-
await server.connect(transport);
9+
getEventTypeInfoHandler,
10+
getEventsHandler,
11+
getTimeBucketsHandler,
12+
listDataCoresHandler,
13+
listEventTypesHandler,
14+
listFlowTypesHandler,
15+
listTenantsHandler,
16+
} from "./tools"
17+
18+
const OIDC_ISSUER = "https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration"
19+
20+
// Parse command line arguments
21+
const { values, positionals } = parseArgs({
22+
args: Bun.argv,
23+
options: {
24+
serviceAccountId: { type: "string" },
25+
serviceAccountKey: { type: "string" },
26+
},
27+
allowPositionals: true,
28+
})
29+
30+
// Log positional arguments if any (for debugging)
31+
if (positionals.length > 0) {
32+
console.warn(`Warning: Unexpected positional arguments: ${positionals.join(", ")}`)
33+
}
34+
35+
const serviceAccountId = values.serviceAccountId as string
36+
const serviceAccountKey = values.serviceAccountKey as string
37+
38+
if (!serviceAccountId || !serviceAccountKey) {
39+
throw new Error("No service account credentials provided")
21040
}
41+
42+
const oidcClient = new OidcClient(serviceAccountId, serviceAccountKey, OIDC_ISSUER)
43+
const flowcoreClient = new FlowcoreClient({
44+
getBearerToken: async () => {
45+
const token = await oidcClient.getToken()
46+
return token.accessToken
47+
},
48+
})
49+
50+
// Create an MCP server
51+
const server = new McpServer({
52+
name: "Flowcore Platform",
53+
version: "1.0.0",
54+
description:
55+
"An MCP server for managing and interacting with Flowcore Platform. For information on the details of the flowcore platform, you can check the Flowcore Platform Data Core, as it houses all actions that have happened in the platform. These actions are called events and are the main building blocks of the platform and housed within the data core inside the event type. The hirearchy of the platform is as follows: Users -> Tenant -> Data Core -> Flow Type -> Event Type -> Events. Tenants and organizations are the same thing in the platform, we are transitioning to use the term tenant. The events are stored in time buckets, and can be fetched by using the get_time_buckets tool.",
56+
})
57+
58+
server.tool("list_tenants", "List all tenants I have access to", listTenantsHandler(flowcoreClient))
59+
server.tool(
60+
"list_data_cores",
61+
"List all data cores for a tenant",
62+
{ tenantId: z.string().describe("The tenant ID to list data cores for") },
63+
listDataCoresHandler(flowcoreClient),
64+
)
65+
66+
server.tool(
67+
"list_flow_types",
68+
"List all flow types for a data core",
69+
{
70+
dataCoreId: z.string().describe("The data core ID to list flow types for"),
71+
},
72+
listFlowTypesHandler(flowcoreClient),
73+
)
74+
75+
server.tool(
76+
"list_event_types",
77+
"List all event types for a flow type",
78+
{
79+
flowTypeId: z.string().describe("The flow type ID to list event types for"),
80+
},
81+
listEventTypesHandler(flowcoreClient),
82+
)
83+
84+
server.tool(
85+
"get_event_type_info",
86+
"Get event information about an event type, like first and last time bucket and 5 example events",
87+
{
88+
eventTypeId: z.string().describe("The event type ID to get information for"),
89+
},
90+
getEventTypeInfoHandler(flowcoreClient),
91+
)
92+
93+
server.tool(
94+
"get_events",
95+
"Get events for an event type, this can be paginated by using the cursor returned from the previous call. This is good for getting the payload of the events to inspect them.",
96+
{
97+
eventTypeId: z.string().describe("The event type ID to get events for"),
98+
timeBucket: z
99+
.string()
100+
.describe(
101+
"The time bucket to get events from, the timebucket is in the format of YYYYMMDDhhiiss, normally the ii and ss are 0000",
102+
),
103+
cursor: z.string().optional().describe("The paging cursor for pagination"),
104+
pageSize: z.number().optional().describe("The number of events per page (default is 10,000)"),
105+
fromEventId: z.string().optional().describe("Start from this event ID"),
106+
afterEventId: z
107+
.string()
108+
.optional()
109+
.describe("Get events after this event ID (not applicable if fromEventId is defined)"),
110+
toEventId: z.string().optional().describe("End at this event ID"),
111+
order: z
112+
.enum(["asc", "desc"])
113+
.optional()
114+
.describe("The order of events (asc or desc). When using desc, pagination and filters are not possible"),
115+
},
116+
getEventsHandler(flowcoreClient),
117+
)
118+
119+
server.tool(
120+
"get_time_buckets",
121+
"Get time buckets for an event type, this is useful for getting the time buckets for an event type, and then using the get_events tool to get the events for a specific time bucket. The time bucket is in the format of YYYYMMDDhhiiss, normally the ii and ss are 0000. It can be paginated by using the cursor returned from the previous call.",
122+
{
123+
eventTypeId: z.string().describe("Event type ID to get time buckets for"),
124+
fromTimeBucket: z.string().optional().describe("Start time bucket (YYYYMMDDhhiiss)"),
125+
toTimeBucket: z.string().optional().describe("End time bucket (YYYYMMDDhhiiss)"),
126+
pageSize: z.number().optional().describe("Number of time buckets per page"),
127+
cursor: z.number().optional().describe("Pagination cursor"),
128+
order: z.enum(["asc", "desc"]).optional().describe("Sort order"),
129+
},
130+
getTimeBucketsHandler(flowcoreClient),
131+
)
132+
133+
server.resource(
134+
"tenant",
135+
new ResourceTemplate("tenant://{tenantId}", { list: undefined }),
136+
tenantResource(flowcoreClient),
137+
)
138+
139+
server.resource(
140+
"data_core",
141+
new ResourceTemplate("data-core://{dataCoreId}", { list: undefined }),
142+
dataCoreResource(flowcoreClient),
143+
)
144+
145+
server.resource(
146+
"flow_type",
147+
new ResourceTemplate("flow-type://{flowTypeId}", { list: undefined }),
148+
flowTypeResource(flowcoreClient),
149+
)
150+
151+
server.resource(
152+
"event_type",
153+
new ResourceTemplate("event-type://{eventTypeId}", { list: undefined }),
154+
eventTypeResource(flowcoreClient),
155+
)
156+
157+
// Start receiving messages on stdin and sending messages on stdout
158+
const transport = new StdioServerTransport()
159+
await server.connect(transport)

0 commit comments

Comments
 (0)