seolinkmap / waasup
Website as a Server using PHP (WaaSuP) - Production-ready SaaS Model Context Protocol (MCP) server for PHP
Requires
- php: ^8.1
- psr/http-factory: ^1.0
- psr/http-message: ^1.0|^2.0
- psr/http-server-middleware: ^1.0
- psr/log: ^1.0|^2.0|^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- monolog/monolog: ^3.0
- phpstan/phpstan: ^1.0
- phpunit/phpunit: ^10.0
- slim/psr7: ^1.0
- slim/slim: ^4.0
- symfony/var-dumper: ^6.0
Suggests
- illuminate/support: For Laravel integration
- monolog/monolog: For PSR-3 logging support
- nyholm/psr7: PSR-17 factory implementation
- slim/psr7: For PSR-7/PSR-17 factories with Slim
- slim/slim: For Slim Framework integration
- symfony/psr-http-message-bridge: For Laravel PSR-7 conversion
README
WaaSuP (Website as a Server using PHP) - A production-ready, SaaS-oriented Model Context Protocol (MCP) server implementation for PHP. Built with enterprise-grade features including OAuth 2.1 authentication, real-time Server-Sent Events (SSE), and comprehensive tool management.
🚀 Try It Live
Want to see WaaSuP in action? Connect to our live demo MCP server with your favorite LLM or agentic tool!
💬 Chat With This Repository
Get instant help with:
- ✅ Installation guidance - Step-by-step setup for your environment
- ⚙️ Configuration assistance - Database setup, OAuth, framework integration
- 🛠️ Custom tool development - Build tools specific to your use case
- 🐛 Troubleshooting - Debug issues with access to the full codebase
- 📚 Code exploration - Understand how features work under the hood
The MCP server has access to our entire repository, documentation, and examples. Ask it anything!
📡 Live MCP Server
https://seolinkmap.com/mcp-repo
This public MCP endpoint showcases the server's capabilities with a complete Website-as-a-Server implementation (authless).
🔗 Need Help Connecting?
New to MCP servers? Learn how to connect: How to Connect to MCP Servers
Once connected, you can explore our entire repository through chat and get real-time help with WaaSuP installation and configuration.
Built by SEOLinkMap - This is our production "web server for chat and agentics" powering AI access to our entire SEO intelligence platform.
✨ Features
- 🔐 OAuth 2.1 Authentication - Complete OAuth flow with RFC 8707 Resource Indicators support for MCP 2025-06-18
- ⚡ Multi-Transport Support - Server-Sent Events (SSE) and Streamable HTTP for real-time message delivery
- 🛠️ Flexible Tool System - Easy tool registration with both class-based and callable approaches
- 🏢 Multi-tenant Architecture - Agency/user context isolation for SaaS applications
- 📊 Production Ready - Comprehensive logging, error handling, and session management
- 🔌 Framework Agnostic - PSR-compliant with Slim Framework and Laravel integration included
- 💾 Database & Memory Storage - Multiple storage backends for different deployment scenarios
- 🌐 CORS Support - Full cross-origin resource sharing configuration
- 🎵 Audio Content Support - Handle audio content in tools and prompts (MCP 2025-03-26+)
- 📝 Structured User Input - Elicitation support for collecting structured data (MCP 2025-06-18)
- 🔄 Progress Notifications - Real-time progress updates with version-aware messaging
- 🏷️ Tool Annotations - Rich tool metadata for better LLM understanding (MCP 2025-03-26+)
- 📦 JSON-RPC Batching - Efficient batch request processing (MCP 2025-03-26)
Requirements
- PHP 8.1 or higher
- Composer
- Database (MySQL/PostgreSQL recommended for production)
MCP Protocol Compliance
WaaSuP implements the complete MCP specification across multiple protocol versions with automatic feature gating:
Feature Matrix Summary
Feature | 2024-11-05 | 2025-03-26 | 2025-06-18 |
---|---|---|---|
Tools | ✅ | ✅ | ✅ |
Prompts | ✅ | ✅ | ✅ |
Resources | ✅ | ✅ | ✅ |
Sampling | ✅ | ✅ | ✅ |
Roots | ✅ | ✅ | ✅ |
Ping | ✅ | ✅ | ✅ |
Progress Notifications | ✅ | ✅ | ✅ |
Tool Annotations | ❌ | ✅ | ✅ |
Audio Content | ❌ | ✅ | ✅ |
Completions | ❌ | ✅ | ✅ |
JSON-RPC Batching | ❌ | ✅ | ❌ |
OAuth 2.1 | ❌ | ❌ | ✅ |
Elicitation | ❌ | ❌ | ✅ |
Structured Outputs | ❌ | ❌ | ✅ |
Resource Links | ❌ | ❌ | ✅ |
Resource Indicators (RFC 8707) | ❌ | ❌ | ✅ (Required) |
Installation
composer require seolinkmap/waasup # For PSR-3 logging support composer require monolog/monolog # For Slim Framework integration composer require slim/slim slim/psr7
Database Setup
- Import the database schema:
1. Open `examples/database/database-schema.sql`
2. Use either MySQL section OR PostgreSQL section (not both)
3. Customize table names/prefixes as needed
4. Create only the tables you need (if using your own table mapping)
- Create your first agency:
INSERT INTO mcp_agencies (uuid, name, active) VALUES ('550e8400-e29b-41d4-a716-446655440000', 'My Company', 1);
- Create an OAuth token:
INSERT INTO mcp_oauth_tokens ( access_token, scope, expires_at, agency_id ) VALUES ( 'your-secret-token-here', 'mcp:read mcp:write', DATE_ADD(NOW(), INTERVAL 1 YEAR), 1 );
Quick Start
Basic Server Setup
<?php require_once __DIR__ . '/vendor/autoload.php'; use Slim\Factory\AppFactory; use Slim\Psr7\Factory\{ResponseFactory, StreamFactory}; use Seolinkmap\Waasup\Storage\DatabaseStorage; use Seolinkmap\Waasup\Tools\Registry\ToolRegistry; use Seolinkmap\Waasup\Prompts\Registry\PromptRegistry; use Seolinkmap\Waasup\Resources\Registry\ResourceRegistry; use Seolinkmap\Waasup\Integration\Slim\SlimMCPProvider; // Database connection $pdo = new PDO('mysql:host=localhost;dbname=mcp_server', $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ]); // Initialize components $storage = new DatabaseStorage($pdo, ['table_prefix' => 'mcp_']); $toolRegistry = new ToolRegistry(); $promptRegistry = new PromptRegistry(); $resourceRegistry = new ResourceRegistry(); $responseFactory = new ResponseFactory(); $streamFactory = new StreamFactory(); // Configuration $config = [ 'server_info' => [ 'name' => 'My MCP Server', 'version' => '0.0.7' ], 'auth' => [ 'context_types' => ['agency'], 'base_url' => 'https://your-domain.com' ] ]; // Create MCP provider $mcpProvider = new SlimMCPProvider( $storage, $toolRegistry, $promptRegistry, $resourceRegistry, $responseFactory, $streamFactory, $config ); // Setup Slim app $app = AppFactory::create(); $app->addErrorMiddleware(true, true, true); // OAuth discovery endpoints $app->get('/.well-known/oauth-authorization-server', [$mcpProvider, 'handleAuthDiscovery']); // Main MCP endpoint $app->map(['GET', 'POST', 'OPTIONS'], '/mcp/{agencyUuid}[/{sessID}]', [$mcpProvider, 'handleMCP']) ->add($mcpProvider->getAuthMiddleware()); $app->run();
Adding Tools
Simple Callable Tool
$toolRegistry->register('get_weather', function($params, $context) { $location = $params['location'] ?? 'Unknown'; return [ 'location' => $location, 'temperature' => '22°C', 'condition' => 'Sunny' ]; }, [ 'description' => 'Get weather information for a location', 'inputSchema' => [ 'type' => 'object', 'properties' => [ 'location' => ['type' => 'string', 'description' => 'Location name'] ], 'required' => ['location'] ] ]);
Built-in Tools
use Seolinkmap\Waasup\Tools\Built\{PingTool, ServerInfoTool}; $toolRegistry->registerTool(new PingTool()); $toolRegistry->registerTool(new ServerInfoTool($config));
Adding Prompts and Resources
// Register a prompt $promptRegistry->register('greeting', function($arguments, $context) { $name = $arguments['name'] ?? 'there'; return [ 'description' => 'A friendly greeting prompt', 'messages' => [[ 'role' => 'user', 'content' => [['type' => 'text', 'text' => "Please greet {$name}."]] ]] ]; }); // Register a resource $resourceRegistry->register('server://status', function($uri, $context) { return [ 'contents' => [[ 'uri' => $uri, 'mimeType' => 'application/json', 'text' => json_encode(['status' => 'healthy', 'timestamp' => date('c')]) ]] ]; });
Framework Integration
Laravel Integration
Add the service provider to your Laravel application:
// config/app.php 'providers' => [ Seolinkmap\Waasup\Integration\Laravel\LaravelServiceProvider::class, ],
Register routes and use the provided controller pattern. See the full Laravel integration example in the /examples
directory.
Standalone (PSR-7)
use Seolinkmap\Waasup\MCPSaaSServer; $server = new MCPSaaSServer($storage, $toolRegistry, $promptRegistry, $resourceRegistry, $config, $logger); $response = $server->handle($request, $response);
Configuration
Server Configuration
$config = [ 'supported_versions' => ['2025-06-18', '2025-03-26', '2024-11-05'], 'server_info' => [ 'name' => 'Your MCP Server', 'version' => '0.0.7' ], 'auth' => [ 'context_types' => ['agency', 'user'], 'validate_scope' => true, 'required_scopes' => ['mcp:read'], 'base_url' => 'https://your-domain.com' ], 'sse' => [ 'keepalive_interval' => 1, 'max_connection_time' => 1800, 'switch_interval_after' => 60 ] ];
Storage Options
Database Storage (Production)
$storage = new DatabaseStorage($pdo, [ 'table_prefix' => 'mcp_', 'cleanup_interval' => 3600 ]);
Memory Storage (Development/Testing)
$storage = new MemoryStorage(); // Add test data $storage->addContext('550e8400-e29b-41d4-a716-446655440000', 'agency', [ 'id' => 1, 'name' => 'Test Agency', 'active' => true ]);
OAuth 2.1 & Authentication
WaaSuP implements complete OAuth 2.1 with RFC 8707 Resource Indicators for MCP 2025-06-18:
- Authorization Code Flow with PKCE (required)
- Resource Indicators for token binding to specific MCP endpoints
- Social Authentication via Google, LinkedIn, and GitHub
- Token Validation with audience claims and scope checking
- Discovery Endpoints for client configuration
Social authentication can be configured for each provider:
$config['google'] = [ 'client_id' => 'your-google-client-id', 'client_secret' => 'your-google-client-secret', 'redirect_uri' => 'https://your-domain.com/oauth/google/callback' ];
Advanced Features
Audio Content Handling (MCP 2025-03-26+)
use Seolinkmap\Waasup\Content\AudioContentHandler; // In your tool return [ 'content' => [ ['type' => 'text', 'text' => 'Here is the audio file:'], AudioContentHandler::createFromFile('/path/to/audio.mp3', 'example.mp3') ] ];
Structured User Input (MCP 2025-06-18)
// Request structured input from user $requestId = $server->requestElicitation( $sessionId, 'Please provide your contact information', [ 'type' => 'object', 'properties' => [ 'name' => ['type' => 'string'], 'email' => ['type' => 'string', 'format' => 'email'] ] ] );
Progress Notifications
// Send progress updates during long-running operations $server->sendProgressNotification($sessionId, 50, 'Processing data...');
API Reference
MCP Methods
Method | Description | Supported Versions |
---|---|---|
initialize |
Initialize MCP session | All |
ping |
Health check | All |
tools/list |
List available tools | All |
tools/call |
Execute a tool | All |
prompts/list |
List available prompts | All |
prompts/get |
Get a prompt | All |
resources/list |
List available resources | All |
resources/read |
Read a resource | All |
completion/complete |
Get completions for arguments | All |
sampling/createMessage |
Request LLM sampling | All |
roots/list |
List available root directories | All |
elicitation/create |
Request user input | 2025-06-18 |
Error Codes
Code | Description |
---|---|
-32000 |
Authentication required |
-32001 |
Session required |
-32600 |
Invalid Request |
-32601 |
Method not found |
-32602 |
Invalid params |
-32603 |
Internal error |
-32700 |
Parse error |
Testing
# Run tests composer test # Static analysis composer analyse # Code formatting composer format
Security
- Token Validation: All requests require valid OAuth tokens with proper audience validation
- Scope Checking: Configurable scope validation for fine-grained access control
- SQL Injection Protection: All database queries use prepared statements
- Session Security: Cryptographically secure session ID generation
- CORS Configuration: Configurable CORS policies for cross-origin requests
- DNS Rebinding Protection: Origin header validation for localhost endpoints
Deployment
Docker
FROM php:8.1-fpm-alpine RUN docker-php-ext-install pdo pdo_mysql COPY . /var/www/html WORKDIR /var/www/html RUN composer install --no-dev --optimize-autoloader EXPOSE 9000 CMD ["php-fpm"]
Nginx Configuration
server { listen 80; server_name your-mcp-server.com; root /var/www/html/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # SSE connection timeout location /mcp/ { proxy_read_timeout 1800s; proxy_send_timeout 1800s; } }
Contributing
We welcome contributions! This server is actively used in production at SEOLinkMap where it powers our SEO intelligence platform.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Add tests for new functionality
- Ensure all tests pass (
composer test
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Development
git clone https://github.com/seolinkmap/waasup.git cd waasup composer install cp .env.example .env # Configure your .env file php -S localhost:8000 -t examples/slim-framework/
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Anthropic for the Model Context Protocol specification
- modelcontextprotocol.io for official MCP documentation and schema
- PHP-FIG for the PSR standards
- Slim Framework for the excellent HTTP foundation
Support & Community
- 🌐 Live Demo: https://seolinkmap.com/mcp-repo (use WaaSuP server to chat with WaaSuP repository... help, install, tool building)
- 📖 Documentation: GitHub Wiki
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
Built with ❤️ by SEOLinkMap for the MCP community.