simplemcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@simplemcpadd 5 and 3"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🐘 simplemcp 🐘
simplemcp is a simple php mcp server. it auto-discovers tool classes via reflection, loads them from a directory you point it at, and authenticates requests via a static bearer token or rotating totp codes (rfc 6238).
installation
composer require vielhuber/simplemcpRelated MCP server: Simple MCP Server
configuration
php -r '$b="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";$r=random_bytes(20);$bits="";for($i=0;$i<20;$i++){$bits.=str_pad(decbin(ord($r[$i])),8,"0",STR_PAD_LEFT);}$s="";for($i=0;$i+5<=strlen($bits);$i+=5){$s.=$b[bindec(substr($bits,$i,5))];}echo "MCP_TOKEN=".$s.PHP_EOL;' > .envauthentication
static mode
Authorization: Bearer <MCP_TOKEN>totp mode
MCP_TOKEN is a base32-encoded shared secret (rfc 6238). the bearer is a fresh 6-digit totp code (30-second window, ±1 step tolerance). the server implements the algorithm natively, no extra library needed. on the client (python/fastmcp):
$authorization_token = (static fn($h) => (static fn($o) => str_pad(((ord($h[$o]) & 0x7f) << 24 | (ord($h[$o+1]) & 0xff) << 16 | (ord($h[$o+2]) & 0xff) << 8 | ord($h[$o+3]) & 0xff) % 1_000_000, 6, '0', STR_PAD_LEFT))(ord($h[19]) & 0xf))(
(static fn($key) => hash_hmac('sha1', pack('N*', 0) . pack('N*', (int) floor(time() / 30)), $key, true))(
(static fn($bits) => implode('', array_map(fn($i) => chr(bindec(substr($bits, $i, 8))), range(0, strlen($bits) - 8, 8))))(
implode('', array_map(fn($c) => str_pad(decbin(strpos('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $c)), 5, '0', STR_PAD_LEFT), str_split(strtoupper($_ENV['MCP_TOKEN']))))
)
));usage
configure the constructor at the bottom of mcp-server.php:
require __DIR__ . '/vendor/autoload.php';
use vielhuber\simplemcp\simplemcp;
new simplemcp(
name: 'my-mcp-server',
log: 'mcp-server.log',
discovery: '.',
auth: 'static', // 'static'|'totp'
env: '.env'
);adding tools
note: simplemcp uses the same
#[McpTool]and#[Schema]attribute syntax asphp-mcp/server. existing tool classes can be migrated by replacinguse PhpMcp\Server\Attributes\McpTool;withuse vielhuber\simplemcp\Attributes\McpTool;(and the same forSchema).
use vielhuber\simplemcp\Attributes\McpTool;
use vielhuber\simplemcp\Attributes\Schema;
class MyTools
{
/**
* Returns the sum of two numbers.
*
* @return int
*/
#[McpTool(name: 'add', description: 'Returns the sum of two numbers.')]
public function add(int $a, int $b): int
{
return $a + $b;
}
/**
* Greets a person by name.
*
* @return string
*/
#[McpTool]
public function greet(
#[Schema(type: 'string', description: 'The name to greet.')]
string $name
): string {
return "Hello, {$name}!";
}
/**
* Finds a user by their ID.
*
* @param int $user_id The unique ID of the user.
*
* @return array{id: int, name: string, email: string} The user data.
*
* @throws \RuntimeException If the user ID is invalid or the user does not exist.
*
*/
#[McpTool(name: 'get_user')]
public function getUser(int $user_id): array
{
if ($user_id <= 0) {
throw new \RuntimeException('User ID must be a positive integer.');
}
$user = db_fetch_row('SELECT * FROM users WHERE ID = ?', $user_id);
if ($user === null) {
throw new \RuntimeException(sprintf('User with ID %d does not exist.', $user_id));
}
return ['id' => $user->ID, 'name' => $user->name, 'email' => $user->email];
}
}note: throw
\RuntimeException(or any\Throwable) to signal errors. simplemcp catches these automatically and returns them as a structured mcp error response withisError: trueand the exception message astext. this is the recommended pattern for invalid input or missing resources — do not returnnullorfalse. generated object schemas reject unknown tool arguments by default. setadditionalProperties: trueexplicitly on a method-level#[Schema]only for backwards compatibility when unknown fields may be ignored.
mcp server
http mode (recommended for remote servers)
{
"mcpServers": {
"simplemcp": {
"url": "https://example.com/mcp-server.php",
"headers": {
"Authorization": "Bearer <MCP_TOKEN>"
}
}
}
}stdio mode (local, via php cli, no auth needed)
{
"mcpServers": {
"simplemcp": {
"command": "/usr/bin/php",
"args": ["/path/to/project/mcp-server.php"]
}
}
}apache configuration
# forward Authorization header
RewriteEngine on
RewriteBase /
CGIPassAuth On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# block public access to .env
<Files ".env">
Require all denied
</Files>This server cannot be deployed
Maintenance
Related MCP Connectors
Host your MCP tool over streamable HTTP in one command.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceA lightweight local MCP server built with FastMCP for exposing custom tools to MCP-compatible clients. Enables local development and testing of MCP tools and resources.1-
- AlicenseNot gradedqualityCmaintenanceA minimal MCP server providing tools for time, calculations, sandboxed file operations, and safe URL fetching over stateless HTTP.12 npmISC
- FlicenseNot gradedqualityCmaintenanceA minimal Python MCP server with bearer token authentication and an example hello tool, deployable on Render for building custom MCP tools.-
- FlicenseNot gradedqualityCmaintenanceA minimal MCP server exposed over HTTP with bearer token authentication, providing echo and get_server_time tools to demonstrate transport and auth mechanics.-