npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flxbl-dev/mcp

v0.6.1-beta

Published

FLXBL Model Context Protocol Server - Bridge between LLM-assisted IDEs and FLXBL

Downloads

338

Readme

FLXBL MCP Server

Model Context Protocol (MCP) server for integrating FLXBL with LLM-assisted IDEs like Cursor, Windsurf, Kiro, and Antigravity.

Overview

The FLXBL MCP Server enables AI assistants in your IDE to:

  • Understand your schema: Read your current FLXBL schema, entities, fields, and relationships
  • Design optimized schemas: Get guidance on FLXBL best practices (graph relationships, field types, naming conventions)
  • Publish schema versions: Create new schema versions directly from your IDE
  • Monitor migrations: Track the status of schema migrations
  • Generate client code: Create TypeScript interfaces, Zod schemas, or Python models from your schema
  • Write queries: Get help with FLXBL's Query DSL and GraphQL

Prerequisites

  • Node.js 18 or later
  • A FLXBL account with an active tenant
  • An API key from your FLXBL dashboard

Installation

Global Installation

npm install -g @flxbl-dev/mcp

Using npx (No Installation)

npx @flxbl-dev/mcp

Configuration

The MCP server requires two environment variables:

| Variable | Description | Example | |----------|-------------|---------| | FLXBL_INSTANCE_URL | URL of your FLXBL instance | https://api.flxbl.dev | | FLXBL_API_KEY | Your FLXBL API key | flxbl_ab12cd34_... |

Getting an API Key

  1. Log in to your FLXBL dashboard
  2. Navigate to SettingsAPI Keys
  3. Click Generate New Key
  4. Copy the key (it won't be shown again)

IDE Setup

Cursor

Add to your Cursor MCP configuration (~/.cursor/mcp.json):

{
  "mcpServers": {
    "flxbl": {
      "command": "npx",
      "args": ["@flxbl-dev/mcp"],
      "env": {
        "FLXBL_INSTANCE_URL": "https://api.flxbl.dev",
        "FLXBL_API_KEY": "your-api-key-here"
      }
    }
  }
}

Windsurf

Add to your Windsurf MCP settings:

{
  "mcp": {
    "servers": {
      "flxbl": {
        "command": "npx",
        "args": ["@flxbl-dev/mcp"],
        "env": {
          "FLXBL_INSTANCE_URL": "https://api.flxbl.dev",
          "FLXBL_API_KEY": "your-api-key-here"
        }
      }
    }
  }
}

VS Code with Continue

Add to your Continue configuration:

{
  "mcpServers": [
    {
      "name": "flxbl",
      "command": "npx",
      "args": ["@flxbl-dev/mcp"],
      "env": {
        "FLXBL_INSTANCE_URL": "https://api.flxbl.dev",
        "FLXBL_API_KEY": "your-api-key-here"
      }
    }
  ]
}

Available Capabilities

Resources (Context)

| Resource URI | Description | |--------------|-------------| | flxbl://about | Product information about FLXBL - graph-based BaaS architecture | | flxbl://tenant | Your tenant context including tenantId (required for GraphQL API) | | flxbl://schema/active | Current active schema with all entities, fields, and relationships | | flxbl://context | Formatted schema summary for LLM context (Markdown) | | flxbl://api/openapi/{schemaId} | OpenAPI 3.0 specification for REST API | | flxbl://api/graphql | GraphQL SDL schema with usage instructions | | flxbl://api/context | Unified API context combining OpenAPI, GraphQL SDL, and schema details | | flxbl://templates | Available schema templates | | flxbl://identity/config | End-user auth settings (requires identity entity in schema) |

Tools (Actions)

| Tool | Description | |------|-------------| | validate_schema | Validate a schema without publishing (dry run) | | publish_schema_version | Create a new schema version with entities and relationships | | check_migration_status | Check the status of a running migration by ID | | generate_client_types | Generate TypeScript/Python types or language-agnostic API contract schema | | list_schema_templates | Browse available pre-built schema templates | | get_api_spec | Get OpenAPI 3.0 specification for the active schema (json or summary format) | | get_graphql_schema | Get GraphQL SDL for the active schema |

generate_client_types Options

| Language | Format | Description | |----------|--------|-------------| | typescript | interface | TypeScript interfaces | | typescript | zod | Zod schemas with full API client | | typescript | class | TypeScript classes | | python | pydantic | Pydantic models | | python | dataclass | Python dataclasses | | any | schema | Language-agnostic JSON API contract |

The schema format returns a comprehensive JSON structure that includes:

  • Entity definitions with field types and constraints
  • Complete REST endpoint documentation
  • Query DSL operators and examples
  • Relationship operation endpoints
  • GraphQL endpoint information
  • Type mapping for multiple languages (TypeScript, Python, Go, Rust)

Prompts (Guidance)

| Prompt | Description | |--------|-------------| | design_flxbl_schema | Guide for designing optimal FLXBL schemas | | schema_design_wizard | Interactive wizard for step-by-step schema design | | generate_query | Help writing FLXBL Query DSL or GraphQL | | query_builder | Interactive wizard for building queries |

Key Concepts

Tenant Context for GraphQL

The GraphQL API requires your tenantId in the URL. Get it from the flxbl://tenant resource:

{
  "tenantId": "your-tenant-uuid",
  "endpoints": {
    "graphql": "/api/v1/dynamic-gql/your-tenant-uuid"
  }
}

FLXBL Architecture

FLXBL is a graph-relational backend-as-a-service that combines:

  • PostgreSQL for schema management and control plane
  • Neo4j for data storage and graph traversal

When you define a schema, FLXBL automatically generates REST and GraphQL APIs. Use the flxbl://about resource for detailed architecture information.

Example Workflows

Designing a New Schema

  1. Open your IDE chat
  2. Ask: "Help me design a schema for a blog platform with posts, authors, and comments"
  3. The AI will use the design_flxbl_schema prompt to guide you through best practices
  4. Review the suggested schema
  5. Use publish_schema_version to create it in FLXBL

Adding Features to Existing Schema

  1. The AI reads your current schema via flxbl://schema/active
  2. Ask: "Add a 'Reviews' feature to my Product entity"
  3. The AI suggests schema changes using relationships
  4. Publish the new version with publish_schema_version
  5. Monitor with check_migration_status

Generating Client Code

  1. Ask: "Generate TypeScript interfaces for my schema"
  2. Use generate_client_types with language: typescript, format: interface
  3. Copy the generated code to your project

Available formats:

# TypeScript interfaces
Generate TypeScript interfaces for my FLXBL schema

# Zod schemas with full API client
Generate Zod schemas for my FLXBL schema

# Python Pydantic models
Generate Pydantic models for my schema

# Python dataclasses
Generate Python dataclasses for my schema

# Language-agnostic API contract (for any language)
Generate API contract schema for my FLXBL schema

The schema format is especially useful when you need to:

  • Generate code in Go, Rust, Java, or other languages
  • Create custom API clients
  • Understand the full API contract including Query DSL and relationships

Using Generated Types with the Dynamic API

Once you've generated types using the MCP, you'll need to connect your application to the FLXBL Dynamic API.

API Base URL

The Dynamic REST API is available at:

{YOUR_FLXBL_URL}/api/v1/dynamic

For local development:

http://localhost:3001/api/v1/dynamic

Authentication

All requests to the Dynamic API must include your API key in the Authorization header:

Authorization: Bearer your_api_key_here

REST Endpoints

For each entity in your schema, FLXBL automatically generates these endpoints:

Entity CRUD Operations

| Method | Endpoint | Description | |--------|----------|-------------| | GET | /api/v1/dynamic/{entity} | List all records | | GET | /api/v1/dynamic/{entity}/:id | Get a record by ID | | POST | /api/v1/dynamic/{entity} | Create a new record | | PUT | /api/v1/dynamic/{entity}/:id | Full update (replace) | | PATCH | /api/v1/dynamic/{entity}/:id | Partial update | | DELETE | /api/v1/dynamic/{entity}/:id | Delete a record | | POST | /api/v1/dynamic/{entity}/query | Query with filters (Query DSL) |

Relationship Operations

| Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/v1/dynamic/{entity}/:id/relationships/{rel} | Create a relationship | | GET | /api/v1/dynamic/{entity}/:id/relationships/{rel}?direction= | Get relationships | | PATCH | /api/v1/dynamic/{entity}/:id/relationships/{rel}/:targetId | Update relationship properties | | DELETE | /api/v1/dynamic/{entity}/:id/relationships/{rel}/:targetId | Delete a relationship |

GraphQL Endpoint

| Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/v1/dynamic-gql/{tenantId} | GraphQL queries and mutations | | GET | /api/v1/dynamic-gql/{tenantId}/schema.graphql | Download GraphQL schema |

Identity API (End-User Authentication)

If your schema has an identity entity (isIdentity: true), these endpoints are automatically enabled for your application's end-users:

| Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/v1/identity/{tenantId}/register | User registration | | POST | /api/v1/identity/{tenantId}/login | User authentication | | GET | /api/v1/identity/{tenantId}/me | Get authenticated user profile | | POST | /api/v1/identity/{tenantId}/verify | Verify email | | POST | /api/v1/identity/{tenantId}/forgot-password | Request password reset | | POST | /api/v1/identity/{tenantId}/reset-password | Reset password | | POST | /api/v1/identity/{tenantId}/refresh | Refresh access token | | POST | /api/v1/identity/{tenantId}/logout | Revoke refresh token |

Important - Dual-Access Pattern: Identity entities are accessible via BOTH:

  • Identity API (/api/v1/identity/...) - For end-user self-service (registration, login)
  • Dynamic API (/api/v1/dynamic/Customer) - For admin operations (list users, bulk updates)

Creating an Identity Entity:

{
  "name": "Customer",
  "isIdentity": true,
  "identifierField": "email",
  "fields": [
    { "name": "email", "type": "STRING", "required": true },
    { "name": "password", "type": "PASSWORD", "required": true },
    { "name": "role", "type": "STRING", "required": false }
  ]
}

The PASSWORD field type is automatically hashed on write and redacted in all API responses.

Query DSL

FLXBL supports a powerful JSON-based Query DSL for complex graph queries:

{
  "where": {
    "age": { "$gte": 18 },
    "status": { "$eq": "active" }
  },
  "orderBy": "createdAt",
  "orderDirection": "DESC",
  "limit": 10
}

Available Operators:

  • Comparison: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin
  • Array: $contains
  • Logical: $and, $or

Graph Traversal for Filtering (related data NOT in response):

{
  "where": { "name": { "$eq": "Alice" } },
  "traverse": [{
    "relationship": "WROTE",
    "direction": "out",
    "where": { "published": { "$eq": true } }
  }]
}

Graph Traversal for Projection (related data IS included in response):

{
  "where": { "name": { "$eq": "Alice" } },
  "traverse": [{
    "relationship": "WROTE",
    "direction": "out",
    "include": true,
    "limit": 10,
    "orderBy": "createdAt",
    "orderDirection": "DESC"
  }]
}

Response: [{ id, name, ..., WROTE: [{ id, title, published, ... }, ...] }]

Important: DELETE Requests

Do NOT include Content-Type: application/json header for DELETE requests without a body. This will cause a 400 error.

Example: TypeScript/React

Important: Entity names in URLs are case-sensitive. Use the exact entity name from your schema (e.g., List not lists).

const API_BASE = 'http://localhost:3001/api/v1/dynamic';
const API_KEY = 'your_api_key_here';

// Headers for requests WITH body
const postHeaders = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json',
};

// Headers for requests WITHOUT body (GET, DELETE)
const getHeaders = {
  'Authorization': `Bearer ${API_KEY}`,
};

// Fetch all items from an entity (note: entity name is case-sensitive!)
async function getLists(): Promise<List[]> {
  const response = await fetch(`${API_BASE}/List`, {
    headers: getHeaders,  // No Content-Type for GET
  });
  
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

// Create a new item
async function createList(data: CreateListDto): Promise<List> {
  const response = await fetch(`${API_BASE}/List`, {
    method: 'POST',
    headers: postHeaders,
    body: JSON.stringify(data),
  });
  
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

// Partial update (PATCH)
async function updateListField(id: string, field: string, value: unknown): Promise<List> {
  const response = await fetch(`${API_BASE}/List/${id}`, {
    method: 'PATCH',
    headers: postHeaders,
    body: JSON.stringify({ [field]: value }),
  });
  
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

// DELETE - Important: No Content-Type header!
async function deleteList(id: string): Promise<void> {
  const response = await fetch(`${API_BASE}/List/${id}`, {
    method: 'DELETE',
    headers: getHeaders,  // No Content-Type for DELETE without body!
  });
  
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
}

// Query with filters
async function findActiveLists(): Promise<List[]> {
  const response = await fetch(`${API_BASE}/List/query`, {
    method: 'POST',
    headers: postHeaders,
    body: JSON.stringify({
      where: { status: { $eq: 'active' } },
      orderBy: 'createdAt',
      orderDirection: 'DESC',
      limit: 10
    }),
  });
  
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

Example: Python

Important: Entity names in URLs are case-sensitive. Use the exact entity name from your schema.

import requests

API_BASE = 'http://localhost:3001/api/v1/dynamic'
API_KEY = 'your_api_key_here'

# Headers for requests WITH body
post_headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json'
}

# Headers for requests WITHOUT body (GET, DELETE)
get_headers = {
    'Authorization': f'Bearer {API_KEY}'
}

# Fetch all items (note: entity name is case-sensitive!)
response = requests.get(f'{API_BASE}/List', headers=get_headers)
items = response.json()

# Create a new item
new_item = {'name': 'My List', 'description': 'A test list'}
response = requests.post(f'{API_BASE}/List', headers=post_headers, json=new_item)
created = response.json()

# Partial update (PATCH)
updates = {'name': 'Updated Name'}
response = requests.patch(f'{API_BASE}/List/{id}', headers=post_headers, json=updates)

# DELETE - Important: No Content-Type header!
response = requests.delete(f'{API_BASE}/List/{id}', headers=get_headers)

# Query with filters
query = {
    'where': {'status': {'$eq': 'active'}},
    'orderBy': 'createdAt',
    'orderDirection': 'DESC',
    'limit': 10
}
response = requests.post(f'{API_BASE}/List/query', headers=post_headers, json=query)
results = response.json()

# Create a relationship
rel_data = {'targetId': 'node_target_id', 'properties': {'role': 'owner'}}
response = requests.post(
    f'{API_BASE}/List/{id}/relationships/BELONGS_TO',
    headers=post_headers,
    json=rel_data
)

Zod Format Includes Full API Client

When you generate types with format: zod, the output includes a comprehensive type-safe API client:

import { createFlxblClient } from './schemas';

const client = createFlxblClient({
  baseUrl: 'http://localhost:3001',
  apiKey: 'your_api_key_here'
});

// Entity CRUD Operations (entity names are case-sensitive!)
const lists = await client.list('List', { limit: 10, orderBy: 'createdAt' });
const list = await client.get('List', 'node_123');
const newList = await client.create('List', { name: 'My List' });
const updated = await client.update('List', 'node_123', { name: 'Updated' });
const patched = await client.patch('List', 'node_123', { status: 'active' });
await client.delete('List', 'node_123');

// Query DSL with type safety
const results = await client.query('List', {
  where: { status: { $eq: 'active' } },
  orderBy: 'createdAt',
  orderDirection: 'DESC',
  limit: 10
});

// Graph traversal for FILTERING (find users who wrote published posts)
const filteredUsers = await client.query('User', {
  where: { name: { $eq: 'Alice' } },
  traverse: [{
    relationship: 'WROTE',
    direction: 'out',
    where: { published: { $eq: true } }
  }]
});

// Graph traversal for PROJECTION (find users AND include their posts)
const usersWithPosts = await client.query('User', {
  where: { name: { $eq: 'Alice' } },
  traverse: [{
    relationship: 'WROTE',
    direction: 'out',
    include: true,  // Include related posts in response
    limit: 10,
    orderBy: 'createdAt',
    orderDirection: 'DESC'
  }]
});
// Response: [{ id, name, WROTE: [{ id, title, published, ... }, ...] }]

// Relationship operations
await client.createRelationship('User', 'user_id', 'MEMBER_OF', {
  targetId: 'group_id',
  properties: { role: 'admin', joinedAt: new Date().toISOString() }
});

const relationships = await client.getRelationships('User', 'user_id', 'MEMBER_OF', 'out');

await client.updateRelationship('User', 'user_id', 'MEMBER_OF', 'group_id', {
  role: 'owner'
});

await client.deleteRelationship('User', 'user_id', 'MEMBER_OF', 'group_id');

Language-Agnostic Schema Format

For generating code in languages other than TypeScript or Python, use the schema format:

Generate API contract schema for my FLXBL schema

This returns a comprehensive JSON structure that can be used to generate code in any language, including:

  • Complete entity and field definitions
  • All REST endpoint specifications
  • Query DSL documentation with examples
  • Type mappings for TypeScript, Python, Go, and Rust

Team Workflow

When working with a team, each team member should have their own API key for IDE integration. This ensures proper audit trails and allows granular permission control.

Setting Up API Keys for Team Members

  1. Tenant Admin Creates API Keys:

    • Log in to the FLXBL dashboard as an admin
    • Navigate to SettingsAPI Keys
    • Create a dedicated API key for each team member
  2. Recommended Scope Configuration by Role:

    | Role | Recommended Scopes | Description | |------|-------------------|-------------| | Developer | entity:*:read, entity:*:create, entity:*:update | Full read access, create and update data | | Designer | entity:*:read, relationship:*:read | Read-only access to explore schema | | Admin | entity:*:*, relationship:*:* | Full access to all operations | | CI/CD | Specific entity scopes only | Minimal scopes for automation |

  3. Team Members Configure Their IDE:

    • Each team member adds the MCP configuration to their IDE with their personal API key
    • Never share API keys between team members

API Key Scopes and Schema Evolution

When you publish a new schema version that removes or renames entities/relationships, existing API keys may have "stale" scopes that reference the old schema:

  • Detection: The API Keys page shows a warning badge next to keys with stale scopes
  • Impact: Stale scopes don't grant access to anything—they're simply ignored
  • Resolution: Update the API key scopes to match the new schema

Best Practice: Use wildcard scopes (e.g., entity:*:read) when possible. Wildcards automatically adapt to schema changes.

Permission Implications

The MCP server operates with the permissions of the API key used:

| Operation | Required Permission | |-----------|-------------------| | Read schema (flxbl://schema/active) | Any valid API key | | Validate schema (validate_schema) | Any valid API key | | Publish schema (publish_schema_version) | entity:*:create or admin role | | Generate types (generate_client_types) | Any valid API key | | Get API specs (get_api_spec, get_graphql_schema) | Any valid API key | | Manage access keys (manage_access_keys) | Admin role only | | Configure identity (configure_identity) | Admin role only |

Best Practices for MCP Key Scopes

  1. Principle of Least Privilege: Only grant the scopes team members need
  2. Use Descriptive Names: Name keys by team member and purpose (e.g., "alice-dev-macbook")
  3. Set Expiration: Use expiration dates for contractor or temporary access
  4. Regular Audits: Review API keys periodically and revoke unused ones
  5. Wildcard Scopes: Prefer wildcards for developers who need to work across the whole schema

Security

  • API Key Isolation: Your API key only has access to your tenant's data
  • No Database Access: The MCP server communicates only via FLXBL's public API
  • Key Redaction: API keys are automatically redacted in logs
  • Read-Only Resources: Resources only read data; mutations require explicit tool calls

Troubleshooting

"Configuration Error: Missing required environment variables"

Ensure both FLXBL_INSTANCE_URL and FLXBL_API_KEY are set in your MCP configuration.

"Invalid or expired API key"

Your API key may have expired or been revoked. Generate a new one from the FLXBL dashboard.

"Could not verify FLXBL connectivity"

Check that:

  1. Your FLXBL_INSTANCE_URL is correct
  2. Your network can reach the FLXBL API
  3. The FLXBL service is operational

MCP Server Not Starting

Check the logs in your IDE's MCP output panel. Common issues:

  • Node.js version too old (requires 18+)
  • npm/npx not in PATH
  • Missing environment variables

Development

Building from Source

cd mcp
npm install
npm run build

Running Locally

FLXBL_INSTANCE_URL=http://localhost:3000 \
FLXBL_API_KEY=your-dev-key \
npm start

Type Checking

npm run typecheck

License

MIT

Support