diff --git a/MCP/swagger-doc_notion/python/Dockerfile b/MCP/swagger-doc_notion/python/Dockerfile new file mode 100644 index 0000000..c705b67 --- /dev/null +++ b/MCP/swagger-doc_notion/python/Dockerfile @@ -0,0 +1,45 @@ +# Multi-stage build for Python MCP Server +FROM python:3.11-alpine AS builder + +# Set working directory +WORKDIR /app + +# Copy requirements file +COPY requirements.txt ./ + +# Install dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Install PyInstaller +RUN pip install --no-cache-dir pyinstaller + +# Copy source code +COPY . . + +# Build the binary +RUN pyinstaller --onefile --name mcp-server main.py + +# Final stage +FROM alpine:latest + +# Install ca-certificates for HTTPS requests +RUN apk --no-cache add ca-certificates + +# Create app directory +WORKDIR /app + +# Copy binary from builder stage +COPY --from=builder /app/dist/mcp-server . + +# Make binary executable +RUN chmod +x mcp-server + +# Expose port (if running in HTTP mode) +EXPOSE 8080 + +# Set non-sensitive environment variables +ENV PORT="8080" +ENV TRANSPORT="http" + +# Run the binary +CMD ["./mcp-server"] diff --git a/MCP/swagger-doc_notion/python/README.md b/MCP/swagger-doc_notion/python/README.md new file mode 100644 index 0000000..1c99d8a --- /dev/null +++ b/MCP/swagger-doc_notion/python/README.md @@ -0,0 +1,202 @@ +# Notion API - Public Beta MCP Server + +This MCP (Model Content Protocol) server provides access to Notion API - Public Beta API functionality through STDIO transport mode with FastMCP. + +## Features + +- FastMCP-based server with decorator pattern +- Automatic tool registration via @mcp.tool() decorators +- Type-safe parameter handling +- Comprehensive error handling and logging +- Easy configuration through environment variables + +## Prerequisites + +- Python 3.10 or later +- pip package manager + +## Installation + +1. Install dependencies: +```bash +pip install -r requirements.txt +``` + +2. Configure environment variables: +```bash +export API_BASE_URL="https://your-api-base-url" +export BEARER_TOKEN="your-bearer-token" +# Alternative authentication options (use only one): +# export API_KEY="your-api-key" +# export BASIC_AUTH="your-basic-auth-credentials" +``` + +## Running the MCP Server + +### STDIO Mode (Default) + +The server runs in STDIO mode by default, which is perfect for direct integration with AI assistants like Cursor: + +```bash +python main.py +``` + +### Configuration for Cursor/Claude Desktop + +Add this to your MCP configuration file (e.g., `~/Library/Application Support/Cursor/User/globalStorage/@anthropic/mcp-server-registry/mcp.json`): + +```json +{ + "mcpServers": { + "notion-api---public-beta-mcp-server": { + "command": "python", + "args": ["/path/to/your/project/main.py"], + "env": { + "API_BASE_URL": "https://your-api-base-url", + "BEARER_TOKEN": "your-bearer-token" + } + } + } +} +``` + +## Environment Variables + +### Required +- `API_BASE_URL`: Base URL for the API endpoint + +### Authentication (use one of the following) +- `BEARER_TOKEN`: Bearer token for OAuth2/Bearer authentication +- `API_KEY`: API key for API key authentication +- `BASIC_AUTH`: Basic authentication credentials (base64 encoded) + +**Note**: At least one authentication variable should be provided unless the API explicitly doesn't require authentication. + +## Development + +For development with auto-reload: + +```bash +# Install development dependencies +pip install -r requirements.txt + +# Run with Python +python main.py +``` + +## Project Structure + +``` +. +├── main.py # Entry point with FastMCP server +├── config.py # Configuration management +├── models.py # Pydantic data models +├── tools/ # Auto-generated tools organized by category +│ ├── __init__.py +│ └── [category]/ # Tools grouped by API endpoint category +│ ├── __init__.py +│ └── *.py # Individual tool implementations +├── requirements.txt # Python dependencies +└── README.md # This file +``` + +## How It Works + +This MCP server is built using FastMCP with a decorator-based architecture: + +1. **FastMCP Server**: Creates an MCP server instance in `main.py` +2. **Tool Decorators**: Each tool is decorated with `@mcp.tool()` for automatic registration +3. **Auto-Import**: Tools are automatically registered when their modules are imported +4. **Type Safety**: Uses Python type hints for parameter validation +5. **Error Handling**: Comprehensive error handling with JSON error responses + +### Example Tool + +```python +from main import mcp + +@mcp.tool() +def get_users(search: str = None, page: int = None) -> str: + """ + Get users from the API. + + Args: + search: Search query for filtering users + page: Page number for pagination + + Returns: + JSON string with user data + """ + # Tool implementation... + return json.dumps(result, indent=2) +``` + +## Authentication Methods + +The server supports multiple authentication methods: + +### Bearer Token (OAuth2) +```bash +export BEARER_TOKEN="your-bearer-token" +``` + +### API Key +```bash +export API_KEY="your-api-key" +``` + +### Basic Authentication +```bash +export BASIC_AUTH="base64-encoded-credentials" +``` + +## Logging + +The server includes comprehensive logging to stderr: +- INFO level: General operations, tool registration +- WARNING level: Skipped operations, missing parameters +- ERROR level: API errors, request failures + +View logs in your MCP client's console or stderr output. + +## Troubleshooting + +### "Missing required parameter" errors +- Check that all required parameters are provided +- Verify parameter names match the tool definition + +### Authentication errors +- Ensure the correct authentication environment variable is set +- Verify your credentials are valid and not expired +- Check that the API_BASE_URL is correct + +### Import errors +- Run `pip install -r requirements.txt` to ensure all dependencies are installed +- Check that you're using Python 3.10 or later + +### Tool not found +- Verify the tool name matches what's shown in your MCP client +- Check the tools directory structure +- Ensure all `__init__.py` files are present + +## Generated Tools + +This server was automatically generated from an OpenAPI specification. Each API endpoint is exposed as an MCP tool with: +- Automatic parameter extraction and validation +- Type-safe parameter handling +- Comprehensive error handling +- JSON response formatting + +Use your MCP client's tool listing feature to see all available tools. + +## Contributing + +This is a generated MCP server. To modify tool behavior: +1. Edit the tool implementation in `tools/[category]/[tool_name].py` +2. Maintain the `@mcp.tool()` decorator for registration +3. Keep the function signature for parameter validation +4. Test changes by running the server locally + +## License + +This generated MCP server follows the same license as the generator tool. \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/build.sh b/MCP/swagger-doc_notion/python/build.sh new file mode 100644 index 0000000..067f48a --- /dev/null +++ b/MCP/swagger-doc_notion/python/build.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Build script for Python MCP server binary +# Usage: ./build.sh + +set -e + +echo "Building Python MCP Server Binary..." + +# Create bin directory if it doesn't exist +mkdir -p bin + +# Create virtual environment if it doesn't exist +if [ ! -d "venv" ]; then + echo "Creating virtual environment..." + python3 -m venv venv +fi + +# Activate virtual environment +echo "Activating virtual environment..." +source venv/bin/activate + +# Install dependencies if requirements.txt exists +if [ -f "requirements.txt" ]; then + echo "Installing dependencies..." + pip install -r requirements.txt +fi + +# Check if PyInstaller is installed, if not install it +if ! command -v pyinstaller &> /dev/null; then + echo "Installing PyInstaller..." + pip install pyinstaller +fi + +# Build the binary +pyinstaller --onefile --name mcp-server --distpath bin main.py + +# Clean up build artifacts +rm -rf build/ *.spec + +# Make binary executable +chmod +x bin/mcp-server + +# Get current directory path +CURRENT_DIR=$(pwd) + +# Update mcp-stdio.json with current directory +if [ -f "mcp-stdio.json" ]; then + echo "Updating mcp-stdio.json with current directory: $CURRENT_DIR" + sed -i.bak "s|\"/path/to/your/python/mcp/server/directory\"|\"$CURRENT_DIR\"|g" mcp-stdio.json + sed -i.bak "s|\"python\"|\"$CURRENT_DIR/python\"|g" mcp-stdio.json + sed -i.bak "s|\"main.py\"|\"$CURRENT_DIR/main.py\"|g" mcp-stdio.json + rm -f mcp-stdio.json.bak + echo "mcp-stdio.json updated successfully!" +else + echo "mcp-stdio.json not found, creating with current directory: $CURRENT_DIR" + cat > mcp-stdio.json << EOF +{ + "mcpServers": { + "mcp-server-stdio": { + "command": "python", + "args": ["$CURRENT_DIR/main.py"], + "env": { + "API_BASE_URL": "https://your.api.url", + "BEARER_TOKEN": "your-token-here" + } + } + } +} +EOF +fi + +echo "Binary built successfully!" +echo "Usage: ./bin/mcp-server or python main.py" +echo "MCP Config: mcp-stdio.json (updated with current directory)" diff --git a/MCP/swagger-doc_notion/python/config.py b/MCP/swagger-doc_notion/python/config.py new file mode 100644 index 0000000..f22fb1a --- /dev/null +++ b/MCP/swagger-doc_notion/python/config.py @@ -0,0 +1,52 @@ +"""API configuration for notion_api_public_beta.""" +import os +from typing import Dict, Any + + +class APIConfig: + """API configuration.""" + + def __init__( + self, + base_url: str = "", + bearer_token: str = "", + api_key: str = "", + basic_auth: str = "", + port: str = "" + ): + self.base_url = base_url + self.bearer_token = bearer_token + self.api_key = api_key + self.basic_auth = basic_auth + self.port = port + + +def load_api_config() -> Dict[str, Any]: + """ + Load API configuration from environment variables. + + Returns: + Configuration dictionary + + Raises: + ValueError: If required configuration is missing + """ + # Check port environment variable + port = os.getenv("PORT") or os.getenv("port", "") + + base_url = os.getenv("API_BASE_URL", "") + + # Check transport environment variable + transport = os.getenv("TRANSPORT") or os.getenv("transport", "") + + # For STDIO mode (not HTTP/HTTPS), API_BASE_URL is required + if transport not in ["http", "HTTP", "https", "HTTPS"] and not base_url: + raise ValueError("API_BASE_URL environment variable not set") + + return { + "base_url": base_url, + "bearer_token": os.getenv("BEARER_TOKEN", ""), + "api_key": os.getenv("API_KEY", ""), + "basic_auth": os.getenv("BASIC_AUTH", ""), + "port": port, + } \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/docker-compose.yml b/MCP/swagger-doc_notion/python/docker-compose.yml new file mode 100644 index 0000000..95161d7 --- /dev/null +++ b/MCP/swagger-doc_notion/python/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.8' + +services: + mcp-server: + build: + context: . + dockerfile: Dockerfile + platforms: + - linux/amd64 + environment: + - PORT=8080 + - TRANSPORT=http + ports: + - "8080:8080" diff --git a/MCP/swagger-doc_notion/python/main.py b/MCP/swagger-doc_notion/python/main.py new file mode 100644 index 0000000..8ea5a6c --- /dev/null +++ b/MCP/swagger-doc_notion/python/main.py @@ -0,0 +1,24 @@ +"""Notion API - Public Beta MCP Server. + +Version: 1.0.0 +""" +import logging +import sys + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + stream=sys.stderr +) +logger = logging.getLogger(__name__) + +# Import server instance first +from server import mcp + +# Import all tools to register them via decorators +from tools import * + +if __name__ == "__main__": + logger.info(f"Starting Notion API - Public Beta MCP Server") + mcp.run(transport="stdio") \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/mcp-docker.json b/MCP/swagger-doc_notion/python/mcp-docker.json new file mode 100644 index 0000000..0bb9e10 --- /dev/null +++ b/MCP/swagger-doc_notion/python/mcp-docker.json @@ -0,0 +1,14 @@ +{ + "mcpServers": { + "mcp-server-docker": { + "command": "docker", + "args": [ + "run", "--rm", "-i", + "-p", "8080:8080", + "-e", "API_BASE_URL=https://your.api.url", + "-e", "BEARER_TOKEN=your-token-here", + "${IMAGE_NAME}" + ] + } + } +} diff --git a/MCP/swagger-doc_notion/python/mcp-http.json b/MCP/swagger-doc_notion/python/mcp-http.json new file mode 100644 index 0000000..7d8b0f7 --- /dev/null +++ b/MCP/swagger-doc_notion/python/mcp-http.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "mcp-server-http": { + "url": "http://localhost:8080/mcp", + "headers": { + "API_BASE_URL": "https://your-api-base-url", + "BEARER_TOKEN": "your-bearer-token" + //Refer to the README.md + } + } + } +} diff --git a/MCP/swagger-doc_notion/python/mcp-https.json b/MCP/swagger-doc_notion/python/mcp-https.json new file mode 100644 index 0000000..b3ad2a2 --- /dev/null +++ b/MCP/swagger-doc_notion/python/mcp-https.json @@ -0,0 +1,14 @@ +{ + "mcpServers": { + "mcp-server-https": { + "url": "https://localhost:8443/mcp", + "headers": { + //Refer to the README.md + "API_BASE_URL": "https://your-api-base-url", + "BEARER_TOKEN": "your-bearer-token", + "CERT_FILE": "./certs/cert.pem", + "KEY_FILE": "./certs/key.pem" + } + } + } +} diff --git a/MCP/swagger-doc_notion/python/models.py b/MCP/swagger-doc_notion/python/models.py new file mode 100644 index 0000000..e571e26 --- /dev/null +++ b/MCP/swagger-doc_notion/python/models.py @@ -0,0 +1,306 @@ +"""Data models for notion_api_public_beta.""" +from typing import Any, Dict, List, Optional +from pydantic import BaseModel, Field + + +class SearchBody(BaseModel): + """SearchBody schema from the OpenAPI specification.""" + query: str = Field(alias="query") # When supplied, limits which pages are returned by comparing the query to the page title + sort: Sorting = Field(alias="sort") # When supplied, sorts the results based on the provided criteria + filter: Filtering = Field(alias="filter") # When supplied, filters the results based on the provided criteria + start_cursor: str = Field(alias="start_cursor") # If supplied, this endpoint will return a page of results starting after the cursor provided or else this endpoint will return the first page of results + page_size: int = Field(alias="page_size") # The number of items from the full list desired in the response. Maximum- 100 + + class Config: + populate_by_name = True + + +class Sorting(BaseModel): + """Sorting schema from the OpenAPI specification.""" + direction: str = Field(alias="direction") # The direction to sort. Possible values include ascending and descending + timestamp: str = Field(alias="timestamp") # The name of the timestamp to sort against. Possible values include last_edited_time + + class Config: + populate_by_name = True + + +class Filtering(BaseModel): + """Filtering schema from the OpenAPI specification.""" + value: str = Field(alias="value") # The value of the property to filter the results by and Possible values for object type include page or database + property: str = Field(alias="property") # The name of the property to filter by. + + class Config: + populate_by_name = True + + +class PaginatedUsers(BaseModel): + """PaginatedUsers schema from the OpenAPI specification.""" + results: List[User] = Field(alias="results") # Array of Users + next_cursor: str = Field(alias="next_cursor") # Next curser position of the user list + has_more: bool = Field(alias="has_more") # Indicates whether there are more user records or not + + class Config: + populate_by_name = True + + +class PageUpdateRequestBody(BaseModel): + """PageUpdateRequestBody schema from the OpenAPI specification.""" + children: List[Dict[str, Any]] = Field(alias="children") # Children pages + + class Config: + populate_by_name = True + + +class PaginatedDatabases(BaseModel): + """PaginatedDatabases schema from the OpenAPI specification.""" + results: List[Database] = Field(alias="results") # Array of Users + next_cursor: str = Field(alias="next_cursor") # Next curser position of the user list + has_more: bool = Field(alias="has_more") # Indicates whether there are more user records or not + + class Config: + populate_by_name = True + + +class ObjectProperties(BaseModel): + """ObjectProperties schema from the OpenAPI specification.""" + author: Dict[str, Any] = Field(alias="Author") # Author of the database + link: Dict[str, Any] = Field(alias="Link") # Related links + name: Dict[str, Any] = Field(alias="Name") # The name of the object + publisher: Dict[str, Any] = Field(alias="Publisher") # Publisher Detail + publishing_release_date: Dict[str, Any] = Field(alias="Publishing/Release Date") # Publishing/Releasing Date + read: Dict[str, Any] = Field(alias="Read") # Read details + status: Dict[str, Any] = Field(alias="Status") # The status ID + summary: Dict[str, Any] = Field(alias="Summary") # The summary of the database + type_field: Dict[str, Any] = Field(alias="Type") # The database type details + + class Config: + populate_by_name = True + + +class ResultDetails(BaseModel): + """ResultDetails schema from the OpenAPI specification.""" + created_time: str = Field(alias="created_time") # The created date/time + has_children: bool = Field(alias="has_children") # Indicates whether it has child object or not + id_field: str = Field(alias="id") # Object ID + last_edited_time: str = Field(alias="last_edited_time") # The last date/time + object_field: str = Field(alias="object") # Object Category + type_field: str = Field(alias="type") # object type + unsupported: Dict[str, Any] = Field(alias="unsupported") # Unsupported + + class Config: + populate_by_name = True + + +class BlockChildrenResponse(BaseModel): + """BlockChildrenResponse schema from the OpenAPI specification.""" + has_more: bool = Field(alias="has_more") # Indicates whether it has more objects or not + next_cursor: Any = Field(alias="next_cursor") # Incidates the position of the response list + object_field: str = Field(alias="object") # The response object + results: List[ResultDetails] = Field(alias="results") # The array of result details + + class Config: + populate_by_name = True + + +class ChildBlockContent(BaseModel): + """ChildBlockContent schema from the OpenAPI specification.""" + child_page: Dict[str, Any] = Field(alias="child_page") # Child page + created_time: str = Field(alias="created_time") # The created date/time + has_children: bool = Field(alias="has_children") # Indicates whether it has children blocks + id_field: str = Field(alias="id") # ID of the block + last_edited_time: str = Field(alias="last_edited_time") # The last edited date/time + object_field: str = Field(alias="object") # Always \"block\" for block types + type_field: str = Field(alias="type") # Type of the block. Possible values include \"paragraph\", \"heading_1\", \"heading_2\", \"heading_3\", \"bulleted_list_item\" etc. + + class Config: + populate_by_name = True + + +class Database(BaseModel): + """Database schema from the OpenAPI specification.""" + created_time: str = Field(alias="created_time") # The created date/time + id_field: str = Field(alias="id") # Database ID + last_edited_time: str = Field(alias="last_edited_time") # The last edited date/time + object_field: str = Field(alias="object") # Object type \"database\" + properties: ObjectProperties = Field(alias="properties") # Object Properties + title: List[Dict[str, Any]] = Field(alias="title") # Title of the database + + class Config: + populate_by_name = True + + +class DatabaseContent(BaseModel): + """DatabaseContent schema from the OpenAPI specification.""" + filter: Dict[str, Any] = Field(alias="filter") # Filter detail + sorts: List[Dict[str, Any]] = Field(alias="sorts") # Sorting details + + class Config: + populate_by_name = True + + +class DatabaseResponse(BaseModel): + """DatabaseResponse schema from the OpenAPI specification.""" + has_more: bool = Field(alias="has_more") # Indicates whether has more objects + next_cursor: Any = Field(alias="next_cursor") # The next position of the result + object_field: str = Field(alias="object") # Object Type \"list\" + results: List[Any] = Field(alias="results") # Database results + + class Config: + populate_by_name = True + + +class PageResponse(BaseModel): + """PageResponse schema from the OpenAPI specification.""" + archived: bool = Field(alias="archived") # Indicates whether it is archived or not + created_time: str = Field(alias="created_time") # The created date/time + id_field: str = Field(alias="id") # ID of the page + last_edited_time: str = Field(alias="last_edited_time") # The last edited date/time + object_field: str = Field(alias="object") # The object type \"page\" + parent: Dict[str, Any] = Field(alias="parent") # Parent Page + properties: ObjectProperties = Field(alias="properties") # Object Properties + + class Config: + populate_by_name = True + + +class PageContent(BaseModel): + """PageContent schema from the OpenAPI specification.""" + properties: Dict[str, Any] = Field(alias="properties") # Page properties + + class Config: + populate_by_name = True + + +class PageUpdatedProperties(BaseModel): + """PageUpdatedProperties schema from the OpenAPI specification.""" + archived: bool = Field(alias="archived") # Indicates whether it is archived or not + created_time: str = Field(alias="created_time") # The created date/time + id_field: str = Field(alias="id") # The ID of the Page + last_edited_time: str = Field(alias="last_edited_time") # The last edited date/time + object_field: str = Field(alias="object") # The object type \"page\" + properties: ObjectProperties = Field(alias="properties") # Object Properties + + class Config: + populate_by_name = True + + +class User(BaseModel): + """User schema from the OpenAPI specification.""" + avatar_url: Any = Field(alias="avatar_url") # avatar URL + id_field: str = Field(alias="id") # User ID + name: str = Field(alias="name") # Name of the User + object_field: str = Field(alias="object") # The object type User + person: Dict[str, Any] = Field(alias="person") # The contact detail + type_field: str = Field(alias="type") # The object type + + class Config: + populate_by_name = True + + +class PageProperties(BaseModel): + """PageProperties schema from the OpenAPI specification.""" + name: str = Field(alias="name") # The ID of the property + type_field: str = Field(alias="type") # Type of the property + + class Config: + populate_by_name = True + + +class DatabaseTitle(BaseModel): + """DatabaseTitle schema from the OpenAPI specification.""" + plain_text: str = Field(alias="plain_text") # The plain text without annotations + href: str = Field(alias="href") # The URL of any link or internal Notion mention in this text, if any + type_field: str = Field(alias="type") # Type of this rich text object. Possible values are- \"text\", \"mention\", \"equation\" + annotation: Annotations = Field(alias="annotation") # Style information which applies to the whole rich text object + + class Config: + populate_by_name = True + + +class Annotations(BaseModel): + """Annotations schema from the OpenAPI specification.""" + bold: bool = Field(alias="bold") # Whether the text is bolded + italic: bool = Field(alias="italic") # Whether the text is italic + strikethrough: bool = Field(alias="strikethrough") # Whether the text is struck through + underline: bool = Field(alias="underline") # Whether the text is underlined + code: bool = Field(alias="code") # Whether the text is \"code style\" + color: str = Field(alias="color") # Color of the text. Possible values are- \"default\", \"gray\", \"brown\", \"orange\", \"yellow\", \"green\", \"blue\", \"purple\", \"pink\", \"red\", \"gray_background\", \"brown_background\", \"orange_background\", \"yellow_background\", \"green_background\", \"blue_background\", \"purple_background\", \"pink_background\", \"red_background\" + + class Config: + populate_by_name = True + + +class PageParent(BaseModel): + """PageParent schema from the OpenAPI specification.""" + database_id: str = Field(alias="database_id") # Database ID + + class Config: + populate_by_name = True + + +class DatabaseParent(BaseModel): + """DatabaseParent schema from the OpenAPI specification.""" + page_id: str = Field(alias="page_id") # Database ID + + class Config: + populate_by_name = True + + +class PageBodyParams(BaseModel): + """PageBodyParams schema from the OpenAPI specification.""" + properties: PageProperties = Field(alias="properties") # Page properties + parent: PageParent = Field(alias="parent") # Parent Page Detail + children: List[Dict[str, Any]] = Field(alias="children") # Page content for the new page + + class Config: + populate_by_name = True + + +class DatabaseBodyParams(BaseModel): + """DatabaseBodyParams schema from the OpenAPI specification.""" + properties: DatabaseProperties = Field(alias="properties") # Property schema of database. The keys are the names of properties as they appear in Notion and the values are property schema objects + parent: DatabaseParent = Field(alias="parent") # Parent Page Detail + title: List[DatabaseTitle] = Field(alias="title") # Property schema of database + + class Config: + populate_by_name = True + + +class DatabaseProperties(BaseModel): + """DatabaseProperties schema from the OpenAPI specification.""" + title: str = Field(alias="title") # Each database must have exactly one database property schema object of type \"title\". This database property controls the title that appears at the top of the page when the page is opened. + rich_text: str = Field(alias="rich_text") # Text database property schema objects + number: Dict[str, Any] = Field(alias="number") # Number database property schema object + select: SelectOptions = Field(alias="select") # Select option + multi_select: List[SelectOptions] = Field(alias="multi_select") # Multi-select database property schema object + date: str = Field(alias="date") # Date database property schema + people: str = Field(alias="people") # People database property schema + files: str = Field(alias="files") # File database property schema object + checkbox: str = Field(alias="checkbox") # Checkbox database property schema object + url: str = Field(alias="url") # URL database property schema object + email: str = Field(alias="email") # Email database property schema object + phone_number: str = Field(alias="phone_number") # Phone number database property schema object + last_edited_time: str = Field(alias="last_edited_time") # Last edited time database property schema object + last_edited_by: str = Field(alias="last_edited_by") # Last edited by database property schema object + created_time: str = Field(alias="created_time") # Created time database property schema object + created_by: str = Field(alias="created_by") # Created by database property schema object + + class Config: + populate_by_name = True + + +class SelectOptions(BaseModel): + """SelectOptions schema from the OpenAPI specification.""" + name: str = Field(alias="name") # Name of the option as it appears in Notion + color: str = Field(alias="color") # Color of the option. Possible values include- default, gray, brown, orange, yellow, green, blue, purple, pink, red + + class Config: + populate_by_name = True + + +class BlockContent(BaseModel): + """BlockContent schema from the OpenAPI specification.""" + text: List[Dict[str, Any]] = Field(alias="text") # block objects + + class Config: + populate_by_name = True \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/requirements.txt b/MCP/swagger-doc_notion/python/requirements.txt new file mode 100644 index 0000000..327711d --- /dev/null +++ b/MCP/swagger-doc_notion/python/requirements.txt @@ -0,0 +1,9 @@ +# Python MCP Server Requirements +# MCP SDK with FastMCP support +mcp[cli]>=1.0.0 + +# HTTP client for API calls +requests>=2.31.0 + +# Data validation +pydantic>=2.0.0 diff --git a/MCP/swagger-doc_notion/python/server.py b/MCP/swagger-doc_notion/python/server.py new file mode 100644 index 0000000..27a373f --- /dev/null +++ b/MCP/swagger-doc_notion/python/server.py @@ -0,0 +1,8 @@ +"""MCP Server instance.""" +import logging +from mcp.server.fastmcp import FastMCP + +logger = logging.getLogger(__name__) + +# Create FastMCP server instance +mcp = FastMCP("Notion API - Public Beta") \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/__init__.py b/MCP/swagger-doc_notion/python/tools/__init__.py new file mode 100644 index 0000000..c4ae2c7 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/__init__.py @@ -0,0 +1,10 @@ +"""Tool modules - auto-registers via @mcp.tool() decorators.""" + +from . import blocks +from . import database +from . import databases +from . import pages +from . import users +from . import v1 + +__all__ = ["blocks", "database", "databases", "pages", "users", "v1"] diff --git a/MCP/swagger-doc_notion/python/tools/blocks/__init__.py b/MCP/swagger-doc_notion/python/tools/blocks/__init__.py new file mode 100644 index 0000000..360e674 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/blocks/__init__.py @@ -0,0 +1,3 @@ +"""Tools in blocks category.""" +from . import append_block_children +from . import retrieve_block_children diff --git a/MCP/swagger-doc_notion/python/tools/blocks/append_block_children.py b/MCP/swagger-doc_notion/python/tools/blocks/append_block_children.py new file mode 100644 index 0000000..17c9952 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/blocks/append_block_children.py @@ -0,0 +1,74 @@ +"""AppendBlockChildren tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def appendblockchildren( + children: list = None +) -> str: + """ + Append block children + + Args: + children: Input parameter: Children pages + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build request body + request_body = {} + if children is not None: + request_body["children"] = children + + # Build URL + url = f"{config['base_url']}/v1/blocks/{id}/children" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + headers["Content-Type"] = "application/json" + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="PATCH", + url=url, + headers=headers, + json=request_body, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/blocks/retrieve_block_children.py b/MCP/swagger-doc_notion/python/tools/blocks/retrieve_block_children.py new file mode 100644 index 0000000..91470f3 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/blocks/retrieve_block_children.py @@ -0,0 +1,77 @@ +"""RetrieveBlockChildren tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def retrieveblockchildren( + page_size: str = None, + Notion_Version: str = None +) -> str: + """ + Retrieve block children + + Args: + page_size: Page size + Notion_Version: API Version + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build query parameters + query_params = {} + if page_size is not None: + query_params["page_size"] = page_size + + # Build URL + url = f"{config['base_url']}/v1/blocks/{id}/children" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + params=query_params, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/database/__init__.py b/MCP/swagger-doc_notion/python/tools/database/__init__.py new file mode 100644 index 0000000..f8b7f83 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/database/__init__.py @@ -0,0 +1,3 @@ +"""Tools in database category.""" +from . import list_all_databases +from . import create_database diff --git a/MCP/swagger-doc_notion/python/tools/database/create_database.py b/MCP/swagger-doc_notion/python/tools/database/create_database.py new file mode 100644 index 0000000..03878bd --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/database/create_database.py @@ -0,0 +1,77 @@ +"""CreateDatabase tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def createdatabase( + value: str, + Notion_Version: str = None +) -> str: + """ + Create a database + + Args: + Notion_Version: API Version + value: DatabaseDetails + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build request body + request_body = {} + request_body["value"] = value + + # Build URL + url = f"{config['base_url']}/v1/databases" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + headers["Content-Type"] = "application/json" + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="POST", + url=url, + headers=headers, + json=request_body, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/database/list_all_databases.py b/MCP/swagger-doc_notion/python/tools/database/list_all_databases.py new file mode 100644 index 0000000..4a32183 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/database/list_all_databases.py @@ -0,0 +1,81 @@ +"""ListAllDatabases tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def listalldatabases( + start_cursor: str = None, + page_size: int = None, + Notion_Version: str = None +) -> str: + """ + List all databases + + Args: + start_cursor: If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results. + page_size: The number of items from the full list desired in the response. Maximum- 100 + Notion_Version: API Version + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build query parameters + query_params = {} + if start_cursor is not None: + query_params["start_cursor"] = start_cursor + if page_size is not None: + query_params["page_size"] = page_size + + # Build URL + url = f"{config['base_url']}/v1/databases" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + params=query_params, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/databases/__init__.py b/MCP/swagger-doc_notion/python/tools/databases/__init__.py new file mode 100644 index 0000000..170e4bd --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/databases/__init__.py @@ -0,0 +1,3 @@ +"""Tools in databases category.""" +from . import query_database +from . import retrieve_database diff --git a/MCP/swagger-doc_notion/python/tools/databases/query_database.py b/MCP/swagger-doc_notion/python/tools/databases/query_database.py new file mode 100644 index 0000000..a1f7d08 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/databases/query_database.py @@ -0,0 +1,78 @@ +"""QueryDatabase tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def querydatabase( + filter: dict = None, + sorts: list = None +) -> str: + """ + Query a Database + + Args: + filter: Input parameter: Filter detail + sorts: Input parameter: Sorting details + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build request body + request_body = {} + if filter is not None: + request_body["filter"] = filter + if sorts is not None: + request_body["sorts"] = sorts + + # Build URL + url = f"{config['base_url']}/v1/databases/{id}/query" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + headers["Content-Type"] = "application/json" + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="POST", + url=url, + headers=headers, + json=request_body, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/databases/retrieve_database.py b/MCP/swagger-doc_notion/python/tools/databases/retrieve_database.py new file mode 100644 index 0000000..8aaffd9 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/databases/retrieve_database.py @@ -0,0 +1,66 @@ +"""RetrieveDatabase tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def retrievedatabase( +) -> str: + """ + Retrieve a database + + Args: + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + + # Build URL + url = f"{config['base_url']}/v1/databases/{id}" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/pages/__init__.py b/MCP/swagger-doc_notion/python/tools/pages/__init__.py new file mode 100644 index 0000000..6eb391e --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/pages/__init__.py @@ -0,0 +1,4 @@ +"""Tools in pages category.""" +from . import retrieve_page +from . import update_page_properties +from . import create_page diff --git a/MCP/swagger-doc_notion/python/tools/pages/create_page.py b/MCP/swagger-doc_notion/python/tools/pages/create_page.py new file mode 100644 index 0000000..8881ee7 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/pages/create_page.py @@ -0,0 +1,77 @@ +"""CreatePage tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def createpage( + value: str, + Notion_Version: str = None +) -> str: + """ + Create a page + + Args: + Notion_Version: API Version + value: PageDetail + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build request body + request_body = {} + request_body["value"] = value + + # Build URL + url = f"{config['base_url']}/v1/pages" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + headers["Content-Type"] = "application/json" + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="POST", + url=url, + headers=headers, + json=request_body, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/pages/retrieve_page.py b/MCP/swagger-doc_notion/python/tools/pages/retrieve_page.py new file mode 100644 index 0000000..0b5a270 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/pages/retrieve_page.py @@ -0,0 +1,66 @@ +"""RetrievePage tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def retrievepage( +) -> str: + """ + Retrieve a Page + + Args: + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + + # Build URL + url = f"{config['base_url']}/v1/pages/{id}" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/pages/update_page_properties.py b/MCP/swagger-doc_notion/python/tools/pages/update_page_properties.py new file mode 100644 index 0000000..3dcc943 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/pages/update_page_properties.py @@ -0,0 +1,74 @@ +"""UpdatePageProperties tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def updatepageproperties( + properties: dict = None +) -> str: + """ + Update Page properties + + Args: + properties: Input parameter: Page properties + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build request body + request_body = {} + if properties is not None: + request_body["properties"] = properties + + # Build URL + url = f"{config['base_url']}/v1/pages/{id}" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + headers["Content-Type"] = "application/json" + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="PATCH", + url=url, + headers=headers, + json=request_body, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/users/__init__.py b/MCP/swagger-doc_notion/python/tools/users/__init__.py new file mode 100644 index 0000000..a5f6a41 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/users/__init__.py @@ -0,0 +1,3 @@ +"""Tools in users category.""" +from . import retrieve_user +from . import list_all_users diff --git a/MCP/swagger-doc_notion/python/tools/users/list_all_users.py b/MCP/swagger-doc_notion/python/tools/users/list_all_users.py new file mode 100644 index 0000000..95388b8 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/users/list_all_users.py @@ -0,0 +1,81 @@ +"""ListAllUsers tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def listallusers( + start_cursor: str = None, + page_size: int = None, + Notion_Version: str = None +) -> str: + """ + List all users + + Args: + start_cursor: If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results. + page_size: The number of items from the full list desired in the response. Maximum- 100 + Notion_Version: API Version + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + # Build query parameters + query_params = {} + if start_cursor is not None: + query_params["start_cursor"] = start_cursor + if page_size is not None: + query_params["page_size"] = page_size + + # Build URL + url = f"{config['base_url']}/v1/users" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + params=query_params, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/users/retrieve_user.py b/MCP/swagger-doc_notion/python/tools/users/retrieve_user.py new file mode 100644 index 0000000..d320651 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/users/retrieve_user.py @@ -0,0 +1,66 @@ +"""RetrieveUser tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def retrieveuser( +) -> str: + """ + Retrieve a user + + Args: + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + + # Build URL + url = f"{config['base_url']}/v1/users/{id}" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + + try: + # Make API request + response = requests.request( + method="GET", + url=url, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file diff --git a/MCP/swagger-doc_notion/python/tools/v1/__init__.py b/MCP/swagger-doc_notion/python/tools/v1/__init__.py new file mode 100644 index 0000000..794af1e --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/v1/__init__.py @@ -0,0 +1,2 @@ +"""Tools in v1 category.""" +from . import search_pages diff --git a/MCP/swagger-doc_notion/python/tools/v1/search_pages.py b/MCP/swagger-doc_notion/python/tools/v1/search_pages.py new file mode 100644 index 0000000..b5054d7 --- /dev/null +++ b/MCP/swagger-doc_notion/python/tools/v1/search_pages.py @@ -0,0 +1,70 @@ +"""SearchPages tool implementation.""" +import json +import logging +from typing import Any +import requests +from server import mcp + +logger = logging.getLogger(__name__) + + +@mcp.tool() +def searchpages( + Notion_Version: str = None +) -> str: + """ + Searches all pages and child pages + + Args: + Notion_Version: API Version + + Returns: + JSON string result + """ + from config import load_api_config + config = load_api_config() + + # Build URL + url = f"{config['base_url']}/v1/search" + + # Build headers + headers = { + "Accept": "application/json", + "X-Request-Source": "Codeglide-MCP-generator", + } + # Set authentication + if config.get("bearer_token"): + headers["Authorization"] = f"Bearer {config['bearer_token']}" + + # Add custom headers + if Notion_Version is not None: + headers["Notion-Version"] = str(Notion_Version) + + try: + # Make API request + response = requests.request( + method="POST", + url=url, + headers=headers, + timeout=30 + ) + + if response.status_code >= 400: + return json.dumps({ + "error": f"API error ({response.status_code})", + "message": response.text + }) + + # Parse response + try: + result = response.json() + return json.dumps(result, indent=2) + except json.JSONDecodeError: + return response.text + + except requests.RequestException as e: + logger.error(f"Request failed: {e}") + return json.dumps({"error": f"Request failed: {str(e)}"}) + except Exception as e: + logger.error(f"Unexpected error: {e}") + return json.dumps({"error": f"Error: {str(e)}"}) \ No newline at end of file