Ctrl K
ComunidadGuías…

lib/local-demo.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { ApiKey, McpServer, RuntimeLog } from "@/lib/types";

export const localDemoUserId = "local-preview";

declare global {
  // Shared by Next route bundles in local demo mode.
  var __astrailLocalGeneratedServers: Map<string, McpServer> | undefined;
}

function localGeneratedServers() {
  globalThis.__astrailLocalGeneratedServers ??= new Map<string, McpServer>();
  return globalThis.__astrailLocalGeneratedServers;
}

export function saveLocalGeneratedServer(server: McpServer) {
  localGeneratedServers().set(server.id, server);
  return server;
}

export function findLocalGeneratedServer(serverId: string) {
  return localGeneratedServers().get(serverId) ?? null;
}

export function updateLocalDemoServer(serverId: string, updates: Partial<McpServer>) {
  const server = localDemoServers().find((item) => item.id === serverId);
  if (!server) return null;
  return saveLocalGeneratedServer({ ...server, ...updates });
}

export function localDemoServers(): McpServer[] {
  const now = new Date().toISOString();
  const generatedServers = Array.from(localGeneratedServers().values())
    .sort((left, right) => String(right.created_at ?? "").localeCompare(String(left.created_at ?? "")));
  const securityFixtures: McpServer[] = process.env.ASTRAIL_ENABLE_LOCAL_SECURITY_FIXTURES === "1"
    ? [
        {
          id: "security-private",
          user_id: localDemoUserId,
          name: "Security private MCP fixture",
          description: "Smoke-test private endpoint auth and runtime policy.",
          source_url: "https://example.com/openapi.json",
          source_type: "openapi_url",
          category: "Security",
          generated_code: null,
          tools_json: [
            {
              name: "private_status",
              description: "Private read fixture.",
              input_schema: { type: "object", properties: {} },
              method: "GET",
              path: "/",
              policy: "block",
            },
            {
              name: "write_probe",
              description: "Write fixture used to verify actor-role enforcement through endpoint catalog calls.",
              input_schema: { type: "object", properties: {} },
              method: "PATCH",
              path: "/api/security-smoke/write-probe",
              policy: "allow",
            },
            {
              name: "invoke_api_endpoint",
              description: "Invoke one reviewed endpoint by ID.",
              input_schema: {
                type: "object",
                properties: {
                  endpoint_id: { type: "string" },
                  arguments: { type: "object" },
                },
                required: ["endpoint_id"],
              },
              method: "ASTRAIL_META",
              path: "/_meta/invoke",
              policy: "allow",
            },
            {
              name: "ssrf_probe",
              description: "Blocked SSRF target fixture.",
              input_schema: { type: "object", properties: {} },
              method: "GET",
              path: "/metadata",
            },
            {
              name: "credential_error",
              description: "Credential redaction fixture.",
              input_schema: { type: "object", properties: {} },
              method: "GET",
              path: "/not-found",
            },
            {
              name: "argument_secret_echo",
              description: "Sensitive argument redaction fixture.",
              input_schema: {
                type: "object",
                properties: {
                  access_token: {
                    type: "string",
                    minLength: 8,
                    "x-astrail-name": "x-echo-value",
                    "x-astrail-in": "header",
                  },
                },
                required: ["access_token"],
                additionalProperties: false,
              },
              method: "GET",
              path: "/api/security-smoke/argument-secret-echo",
            },
          ],
          endpoint_map: [
            {
              method: "GET",
              path: "/",
              base_url: "https://example.com",
              tool_name: "private_status",
              operation_id: "private_status",
              summary: "Private status",
              description: "Private read fixture.",
              parameters: [],
              input_schema: { type: "object", properties: {} },
              operation_kind: "read",
              requires_auth: false,
            },
            {
              method: "PATCH",
              path: "/api/security-smoke/write-probe",
              base_url: process.env.ASTRAIL_SECURITY_SMOKE_UPSTREAM_BASE_URL ?? "http://127.0.0.1:3000",
              tool_name: "write_probe",
              operation_id: "write_probe",
              summary: "Write probe",
              description: "Must be denied for read-only actor roles, including through invoke_api_endpoint.",
              parameters: [],
              input_schema: { type: "object", properties: {} },
              operation_kind: "write",
              requires_auth: false,
            },
            {
              method: "GET",
              path: "/metadata",
              base_url: "http://169.254.169.254",
              tool_name: "ssrf_probe",
              operation_id: "ssrf_probe",
              summary: "SSRF probe",
              description: "Blocked metadata service target.",
              parameters: [],
              input_schema: { type: "object", properties: {} },
              operation_kind: "read",
              requires_auth: false,
            },
            {
              method: "GET",
              path: "/not-found",
              base_url: "https://example.com",
              tool_name: "credential_error",
              operation_id: "credential_error",
              summary: "Credential error",
              description: "Forces an upstream error while provider credentials are injected.",
              parameters: [],
              input_schema: { type: "object", properties: {} },
              operation_kind: "read",
              requires_auth: true,
            },
            {
              method: "GET",
              path: "/api/security-smoke/argument-secret-echo",
              base_url: process.env.ASTRAIL_SECURITY_SMOKE_UPSTREAM_BASE_URL ?? "http://127.0.0.1:3000",
              tool_name: "argument_secret_echo",
              operation_id: "argument_secret_echo",
              summary: "Sensitive argument echo",
              description: "Echoes a sensitive tool argument through a non-sensitive upstream header name.",
              parameters: [
                { name: "x-echo-value", in: "header", required: true, schema: { type: "string" } },
              ],
              input_schema: {
                type: "object",
                properties: {
                  access_token: {
                    type: "string",
                    minLength: 8,
                    "x-astrail-name": "x-echo-value",
                    "x-astrail-in": "header",
                  },
                },
                required: ["access_token"],
                additionalProperties: false,
              },
              operation_kind: "read",
              requires_auth: false,
            },
          ],
          diagnostics: ["Local security smoke fixture."],
          status: "live",
          validation_status: "passed",
          generation_status: "completed",
          is_public: false,
          hosted_endpoint: "/api/mcp/security-private",
          call_count: 0,
          protocol_version: "2024-11-05",
          runtime_policy: {
            roles: { operator: { max_action_level: "read" } },
          },
          created_at: now,
        },
        {
          id: "security-public",
          user_id: localDemoUserId,
          name: "Security public MCP fixture",
          description: "Smoke-test public endpoint filtering and permission denial.",
          source_url: "https://example.com/openapi.json",
          source_type: "openapi_url",
          category: "Security",
          generated_code: null,
          tools_json: [
            {
              name: "public_echo",
              description: "Public read fixture.",
              input_schema: {
                type: "object",
                properties: {
                  q: { type: "string", description: "Public query." },
                },
                required: ["q"],
                additionalProperties: false,
              },
              method: "GET",
              path: "/",
              x_astrail: {
                visibility: "public",
                risk: "read",
                requires_auth: false,
                auth_schemes: [],
                required_scopes: [],
                prerequisites: [],
                agent_instructions: ["Read-only public fixture."],
                example_arguments: { q: "hello" },
              },
            },
            {
              name: "private_delete_everything",
              description: "Private destructive fixture SECRET_DO_NOT_LEAK.",
              input_schema: {
                type: "object",
                properties: {
                  confirmation: { type: "string", description: "SECRET_DO_NOT_LEAK" },
                },
                required: ["confirmation"],
              },
              method: "DELETE",
              path: "/private",
              visibility: "private",
              x_astrail: {
                visibility: "private",
                risk: "destructive",
                requires_auth: true,
                auth_schemes: ["bearer"],
                required_scopes: ["SECRET_DO_NOT_LEAK"],
                prerequisites: ["SECRET_DO_NOT_LEAK"],
                agent_instructions: ["SECRET_DO_NOT_LEAK"],
                example_arguments: { confirmation: "SECRET_DO_NOT_LEAK" },
              },
            },
          ],
          endpoint_map: [
            {
              method: "GET",
              path: "/",
              base_url: "https://example.com",
              tool_name: "public_echo",
              operation_id: "public_echo",
              summary: "Public echo",
              description: "Public read fixture.",
              parameters: [
                { name: "q", in: "query", required: true, schema: { type: "string" } },
              ],
              input_schema: {
                type: "object",
                properties: {
                  q: { type: "string" },
                },
                required: ["q"],
                additionalProperties: false,
              },
              operation_kind: "read",
              requires_auth: false,
              visibility: "public",
            },
            {
              method: "DELETE",
              path: "/private",
              base_url: "https://example.com",
              tool_name: "private_delete_everything",
              operation_id: "private_delete_everything",
              summary: "Private destructive endpoint",
              description: "SECRET_DO_NOT_LEAK",
              parameters: [],
              input_schema: {
                type: "object",
                properties: {
                  confirmation: { type: "string" },
                },
                required: ["confirmation"],
              },
              operation_kind: "destructive",
              requires_auth: true,
              visibility: "private",
            },
          ],
          diagnostics: ["Local security smoke fixture."],
          status: "live",
          validation_status: "passed",
          generation_status: "completed",
          is_public: true,
          hosted_endpoint: "/api/mcp/security-public",
          call_count: 0,
          protocol_version: "2024-11-05",
          created_at: now,
        },
      ]
    : [];
  const demoServers: McpServer[] = [
    {
      id: "local-website-mcp",
      user_id: localDemoUserId,
      name: "Hacker News browser server",
      description: "Website-to-MCP preview generated from a public website.",
      source_url: "https://news.ycombinator.com",
      source_type: "website",
      category: "Website",
      generated_code: null,
      tools_json: [
        {
          name: "browser_open_page",
          description: "Open the page and summarize visible public content.",
          input_schema: { type: "object", properties: {} },
          method: "BROWSER",
          path: "body",
        },
      ],
      endpoint_map: [
        {
          method: "BROWSER",
          path: "body",
          runtime_kind: "browser",
          browser_action: "open_page",
          selector: "body",
          target_url: "https://news.ycombinator.com/",
          tool_name: "browser_open_page",
          operation_id: "browser_open_page",
          summary: "Open page",
          description: "Open the inspected website and return a public page summary.",
          parameters: [],
          requires_auth: false,
        },
      ],
      diagnostics: ["Local demo server. Connect persistent workspace storage to save generated endpoint details."],
      status: "live",
      validation_status: "passed",
      generation_status: "completed",
      is_public: true,
      hosted_endpoint: "/api/mcp/local-website-mcp",
      call_count: 128,
      protocol_version: "2024-11-05",
      created_at: now,
    },
    {
      id: "local-openapi",
      user_id: localDemoUserId,
      name: "Petstore OpenAPI server",
      description: "Demo endpoint map generated from the Swagger Petstore spec.",
      source_url: "https://petstore.swagger.io/v2/swagger.json",
      source_type: "openapi_url",
      category: "OpenAPI",
      generated_code: null,
      tools_json: [
        {
          name: "list_inventory",
          description: "List inventory counts from the sample Petstore API.",
          input_schema: { type: "object", properties: {} },
          method: "GET",
          path: "/store/inventory",
        },
      ],
      endpoint_map: [
        {
          method: "GET",
          path: "/store/inventory",
          base_url: "https://petstore.swagger.io/v2",
          tool_name: "list_inventory",
          operation_id: "list_inventory",
          summary: "List inventory",
          description: "List inventory counts from the sample Petstore API.",
          parameters: [],
          requires_auth: false,
        },
      ],
      diagnostics: ["Local demo server. Connect persistent workspace storage to save generated endpoint details."],
      status: "live",
      validation_status: "passed",
      generation_status: "completed",
      is_public: true,
      hosted_endpoint: "/api/mcp/local-openapi",
      call_count: 42,
      protocol_version: "2024-11-05",
      created_at: now,
    },
    {
      id: "local-code-mode",
      user_id: localDemoUserId,
      name: "Petstore Code Mode server",
      description: "Demo Code Mode MCP endpoint with search_docs and execute over a Petstore endpoint map.",
      source_url: "https://petstore.swagger.io/v2/swagger.json",
      source_type: "openapi_url",
      category: "OpenAPI",
      generated_code: null,
      tools_json: [
        {
          name: "search_docs",
          description: "Search SDK-style documentation for the generated Petstore API.",
          input_schema: {
            type: "object",
            properties: {
              query: { type: "string", description: "Search text." },
              limit: { type: "integer", description: "Maximum docs to return." },
            },
          },
          method: "ASTRAIL_CODE",
          path: "search_docs",
        },
        {
          name: "execute",
          description: "Run SDK-style TypeScript calls compiled through Astrail's no-eval endpoint map.",
          input_schema: {
            type: "object",
            properties: {
              code: {
                type: "string",
                description: "Example: async function run(client) { return await client.store.getInventory({}); }",
              },
            },
            required: ["code"],
          },
          method: "ASTRAIL_CODE",
          path: "execute",
        },
      ],
      endpoint_map: [
        {
          method: "GET",
          path: "/store/inventory",
          base_url: "https://petstore.swagger.io/v2",
          tool_name: "petstore_openapi_server_get_inventory",
          operation_id: "getInventory",
          summary: "List inventory",
          description: "Returns pet inventories by status from the sample Petstore API.",
          tags: ["store"],
          resource: "store",
          operation_kind: "read",
          parameters: [],
          input_schema: { type: "object", properties: {} },
          requires_auth: false,
        },
      ],
      diagnostics: ["Local Code Mode demo server. Connect persistent workspace storage to save generated endpoint details."],
      status: "live",
      validation_status: "passed",
      generation_status: "completed",
      is_public: true,
      hosted_endpoint: "/api/mcp/local-code-mode",
      call_count: 17,
      protocol_version: "2024-11-05",
      created_at: now,
    },
    {
      id: "runtime-permissions-demo",
      user_id: localDemoUserId,
      name: "Petstore Runtime Permissions demo",
      description: "Local demo endpoint for Astrail runtime method permissions.",
      source_url: "https://petstore.swagger.io/v2/swagger.json",
      source_type: "openapi_url",
      category: "OpenAPI",
      generated_code: null,
      tools_json: [
        {
          name: "list_inventory",
          description: "List inventory counts from the sample Petstore API.",
          input_schema: { type: "object", properties: {} },
          method: "GET",
          path: "/store/inventory",
        },
        {
          name: "delete_pet",
          description: "Delete a pet from the sample Petstore API.",
          input_schema: {
            type: "object",
            properties: {
              petId: { type: "integer", description: "Pet ID to delete.", "x-astrail-name": "petId", "x-astrail-in": "path" },
            },
            required: ["petId"],
          },
          method: "DELETE",
          path: "/pet/{petId}",
        },
        {
          name: "search_docs",
          description: "Search SDK-style documentation for the generated Petstore API.",
          input_schema: {
            type: "object",
            properties: {
              query: { type: "string", description: "Search text." },
              limit: { type: "integer", description: "Maximum docs to return." },
            },
          },
          method: "ASTRAIL_CODE",
          path: "search_docs",
        },
        {
          name: "execute",
          description: "Run SDK-style TypeScript calls compiled through Astrail's no-eval endpoint map.",
          input_schema: {
            type: "object",
            properties: {
              code: { type: "string", description: "Example: await client.store.getInventory({});" },
              result_mode: { type: "string", enum: ["compact", "full"] },
            },
            required: ["code"],
          },
          method: "ASTRAIL_CODE",
          path: "execute",
        },
      ],
      endpoint_map: [
        {
          method: "GET",
          path: "/store/inventory",
          base_url: "https://petstore.swagger.io/v2",
          tool_name: "list_inventory",
          operation_id: "getInventory",
          summary: "List inventory",
          description: "Returns pet inventories by status from the sample Petstore API.",
          tags: ["store"],
          resource: "store",
          operation_kind: "read",
          parameters: [],
          input_schema: { type: "object", properties: {} },
          requires_auth: false,
        },
        {
          method: "DELETE",
          path: "/pet/{petId}",
          base_url: "https://petstore.swagger.io/v2",
          tool_name: "delete_pet",
          operation_id: "deletePet",
          summary: "Delete pet",
          description: "Deletes a pet from the sample Petstore API.",
          tags: ["pet"],
          resource: "pet",
          operation_kind: "destructive",
          parameters: [{ name: "petId", in: "path", required: true, schema: { type: "integer" } }],
          input_schema: {
            type: "object",
            properties: {
              petId: { type: "integer", description: "Pet ID to delete.", "x-astrail-name": "petId", "x-astrail-in": "path" },
            },
            required: ["petId"],
          },
          requires_auth: false,
        },
      ],
      runtime_policy: {
        read_only: true,
        allow_http_gets: true,
        allowed_resources: [{ pattern: "^store$", regex: true, match: "resource" }],
        blocked_methods: [
          "client.pet.deletePet",
          { pattern: "delete_pet", match: "endpoint_id" },
        ],
      },
      diagnostics: ["Local runtime permissions demo server."],
      status: "live",
      validation_status: "passed",
      generation_status: "completed",
      is_public: true,
      hosted_endpoint: "/api/mcp/runtime-permissions-demo",
      call_count: 0,
      protocol_version: "2024-11-05",
      created_at: now,
    },
  ];

  const generatedIds = new Set(generatedServers.map((server) => server.id));
  return [
    ...generatedServers,
    ...securityFixtures,
    ...demoServers.filter((server) => !generatedIds.has(server.id)),
  ];
}

export function localDemoApiKeys(): ApiKey[] {
  return [
    {
      id: "00000000-0000-4000-8000-000000000001",
      user_id: localDemoUserId,
      name: "Anthropic demo key",
      key_preview: "ag_demo...ready",
      last_used: new Date(Date.now() - 12 * 60 * 1000).toISOString(),
      created_at: new Date().toISOString(),
    },
  ];
}

export function localDemoLogs(): RuntimeLog[] {
  return [
    {
      id: "log_1",
      server_id: "local-website-mcp",
      user_id: localDemoUserId,
      tool_name: "browser_open_page",
      status: "success",
      method: "BROWSER",
      path: "body",
      execution_mode: "website_browser_runtime",
      upstream_status: 200,
      trace_id: "agt_demo_browser_01",
      attempt_count: 1,
      error_code: null,
      error: null,
      latency_ms: 1180,
      created_at: new Date(Date.now() - 9 * 60 * 1000).toISOString(),
    },
    {
      id: "log_2",
      server_id: "local-openapi",
      user_id: localDemoUserId,
      tool_name: "list_pets",
      status: "success",
      method: "GET",
      path: "/pets",
      execution_mode: "safe_rest_execution",
      upstream_status: 200,
      trace_id: "agt_demo_openapi_01",
      attempt_count: 1,
      error_code: null,
      error: null,
      latency_ms: 243,
      created_at: new Date(Date.now() - 38 * 60 * 1000).toISOString(),
    },
  ];
}