feat: WIP kittens

pull/715/head
Travis Fischer 2025-05-31 17:50:24 +07:00
rodzic 67f564bff8
commit b0d3dcf589
8 zmienionych plików z 74 dodań i 19 usunięć

Wyświetl plik

@ -34,9 +34,9 @@
"@agentic/platform-types": "workspace:*",
"@agentic/platform-validators": "workspace:*",
"@hono/zod-validator": "catalog:",
"@modelcontextprotocol/sdk": "catalog:",
"eventid": "catalog:",
"hono": "catalog:",
"@modelcontextprotocol/sdk": "catalog:",
"type-fest": "catalog:"
},
"devDependencies": {

Wyświetl plik

@ -11,13 +11,15 @@ export async function enforceRateLimit(
method,
pathname
}: {
id: string
id?: string
interval: number
maxPerInterval: number
method: string
pathname: string
}
) {
assert(id, 400, 'Unauthenticated requests must have a valid IP address')
// TODO
assert(ctx, 500, 'not implemented')
assert(id, 500, 'not implemented')

Wyświetl plik

@ -2,7 +2,7 @@ import { assert } from '@agentic/platform-core'
import type { AdminConsumer, Context } from './types'
export async function getConsumer(
export async function getAdminConsumer(
ctx: Context,
token: string
): Promise<AdminConsumer> {

Wyświetl plik

@ -4,7 +4,7 @@ import { parseFaasIdentifier } from '@agentic/platform-validators'
import type { Context } from './types'
export async function getDeployment(
export async function getAdminDeployment(
ctx: Context,
identifier: string
): Promise<{ deployment: AdminDeployment; toolPath: string }> {

Wyświetl plik

@ -2,8 +2,9 @@ import type { PricingPlan, RateLimit } from '@agentic/platform-types'
import { assert } from '@agentic/platform-core'
import type { AdminConsumer, Context, ResolvedOriginRequest } from './types'
import { getConsumer } from './get-consumer'
import { getDeployment } from './get-deployment'
import { enforceRateLimit } from './enforce-rate-limit'
import { getAdminConsumer } from './get-admin-consumer'
import { getAdminDeployment } from './get-admin-deployment'
import { getTool } from './get-tool'
import { updateOriginRequest } from './update-origin-request'
@ -23,8 +24,13 @@ export async function resolveOriginRequest(
const { search, pathname } = requestUrl
const method = req.method.toLowerCase()
const requestPathParts = pathname.split('/')
const requestPath =
requestPathParts[0] === 'mcp'
? requestPathParts.slice(1).join('/')
: pathname
const { deployment, toolPath } = await getDeployment(ctx, pathname)
const { deployment, toolPath } = await getAdminDeployment(ctx, requestPath)
const tool = getTool({
method,
@ -50,7 +56,7 @@ export async function resolveOriginRequest(
.trim()
if (token) {
consumer = await getConsumer(ctx, token)
consumer = await getAdminConsumer(ctx, token)
assert(consumer, 401, `Invalid auth token "${token}"`)
assert(
consumer.isStripeSubscriptionActive,
@ -155,12 +161,11 @@ export async function resolveOriginRequest(
}
}
// enforce requests rate limits
if (rateLimit) {
await enforceRateLimit(ctx, {
id: consumer ? consumer.id : ip,
duration: rateLimit.interval * 1000,
max: rateLimit.maxPerInterval,
id: consumer?.id ?? ip,
interval: rateLimit.interval * 1000,
maxPerInterval: rateLimit.maxPerInterval,
method,
pathname
})

Wyświetl plik

@ -0,0 +1,27 @@
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'
import type { Context, ResolvedOriginRequest } from './lib/types'
// TODO: https://github.com/modelcontextprotocol/servers/blob/8fb7bbdab73eddb42aba72e8eab81102efe1d544/src/everything/sse.ts
// TODO: https://github.com/cloudflare/agents
const transports: Map<string, SSEServerTransport> = new Map<
string,
SSEServerTransport
>()
export async function handleMCPRequest(
ctx: Context,
resolvedOriginRequest: ResolvedOriginRequest
) {
const serverTransport = new SSEServerTransport()
const server = new McpServer({
name: 'weather',
version: '1.0.0',
capabilities: {
resources: {},
tools: {}
}
})
}

Wyświetl plik

@ -62,6 +62,17 @@ export default {
const resolvedOriginRequest = await resolveOriginRequest(ctx)
try {
switch (resolvedOriginRequest.deployment.originAdapter.type) {
case 'openapi':
break
case 'raw':
break
case 'mcp':
break
}
const originReqCacheKey = await getOriginRequestCacheKey(originReq)
originStartTime = Date.now()

Wyświetl plik

@ -7,8 +7,6 @@
## TODO
- **api gateway**
- signed requests
- **webapp**
- end-to-end working examples
- raw
@ -25,7 +23,7 @@
- (openauth password emails and `sendCode`)
- stripe-related billing emails
- auth
- custom auth pages
- custom auth pages for `openauth`
- re-add support for teams / organizations
- consider switching to [consola](https://github.com/unjs/consola) for logging?
- consider switching to `bun` (for `--hot` reloading!!)
@ -36,11 +34,23 @@
- validate stability of pricing plan slugs across deployments
- same for pricing plan line-items
- replace `ms` package
- API gateway MCP server vs OpenAPI API gateway
- share hono middleware and utils across apps/api and apps/gateway
- or combine these together? ehhhh
- add username / team name blacklist
- admin, internal, mcp, etc
- admin, internal, mcp, sse, etc
- **API gateway**
- share hono middleware and utils across apps/api and apps/gateway
- or combine these together? ehhhh
- MCP server vs REST gateway on public and internal sides
- RAW: `METHOD gateway.agentic.so/deploymentIdentifier/<pathname>`
- => Raw HTTP: `METHOD originUrl/<pathname>` simple HTTP proxy request
- REST: `POST gateway.agentic.so/deploymentIdentifier/toolName`
- => MCP: `MCPClient.callTool` with JSON body parameters
- => OpenAPI: `GET/POST/ETC originUrl/toolName` operation with transformed JSON body params
- MCP: `mcp.agentic.so/deploymentIdentifier/sse` MCP server
- => MCP: `MCPClient.callTool` just proxying tool call
- => OpenAPI: `GET/POST/ETC originUrl/toolName` operation with transformed tool params
- add support for caching
- add support for custom headers on response
- signed requests
## License