MCPController
MMO\core\controllers · 1 symbol · generated 30 Sep 2026
MCPController
MCPController.php:50MCPController — a Model Context Protocol (https://modelcontextprotocol.io) server that exposes the MMOFramework itself to any MCP-compatible AI agent (Claude, or any other client speaking the protocol).
- Namespace
MMO\core\controllers- Extends
- aController
Index
| DOC_INDEX | ||
| ERROR_INTERNAL | ||
| ERROR_INVALID_PARAMS | ||
| ERROR_INVALID_REQUEST | ||
| ERROR_METHOD_NOT_FOUND | ||
| ERROR_PARSE | ||
| GUIDE | The full coding guide: also served verbatim as initialize's instructions and as the mmoframework://guide resource. | |
| INDEX_LIMIT | ||
| JSONRPC_VERSION | ||
| LATEST_PROTOCOL_VERSION | ||
| PROMPTS | Every prompt this server exposes through prompts/list/prompts/get. | |
| SEARCH_LIMIT | ||
| SEARCH_STOPWORDS | The words a relaxed search drops first, whatever their frequency: a question asks with them, documentation is not written with them, and how common they are here says nothing about that. | |
| SEARCH_WINDOW | ||
| SECTION_CHARS | ||
| SECTION_LINES | ||
| SECTION_MATCHES | How many of the best matches come back with the whole section holding them, and how much of one is worth returning. | |
| SUPPORTED_PROTOCOL_VERSIONS | ||
| SYMBOL_LIMIT | ||
| TOOLS | Every tool this server exposes through tools/list/tools/call. | |
| discovered | ||
| dataListEntities($repositoryFilter) | ||
| dataListFunctions($namespace) | ||
| dataListPackages() | ||
| dataListRoutes($controllerFilter) | ||
| describeParameterDocs($fn) | What each parameter's @param says: an options class (PrintOptions) explains its options there. | |
| describeParameters($fn) | ||
| discoverDocuments() | ||
| discoverRepositories() | ||
| dispatchMethod($method, $params) | ||
| documentedPackages() | ||
| documentedSymbol($name) | ||
| documentPaths() | ||
| getPackages() | The packages this server documents: every included one, then, with $discovered, every other package PackageManager read the manifest of (its most recent version), by name. | |
| mcpInitialize($params) | ||
| mcpPromptsGet($params) | ||
| mcpPromptsList($params) | ||
| mcpResourcesList($params) | ||
| mcpResourcesRead($params) | ||
| mcpToolsCall($params) | ||
| mcpToolsList($params) | ||
| onRoute($route) | ||
| promptCreateController($args) | ||
| promptCreateEntity($args) | ||
| resourceContents($uri, $mimeType, $text) | ||
| routeMCP($route) | ||
| routeStream($route) | ||
| rpcError($id, $code, $message) | ||
| rpcResult($id, $result) | ||
| searchDocuments($documents, $query, $missing) | ||
| searchLines($lines, $words) | Where $lines hold every one of $words: each line holding them all, or else the fewest consecutive lines (at most SEARCH_WINDOW) holding them together. | |
| searchRank($excerpt, $oneLine, $words, $phrase) | What ranks a match of searchDocuments(), lowest first: its tier (0 when it holds the exact phrase, 1 when it is a single line, 2 when its words spread over several), then how many words it only fin… | |
| searchRelaxed($documents, $query, $package) | What a query matches when no line holds all of it: its most common words are dropped, one at a time, until something matches. | |
| searchSection($lines, $at) | The markdown section holding line $at: from the heading above it down to the next heading of the same level or higher, a deeper one belonging to it. | |
| searchSections($matches, $documents) | The matches, the best few carrying the whole markdown section holding them: its heading, and its lines down to the next heading of the same level or higher. | |
| searchSymbols($query, $package) | The documented symbols a query names (DocIndex::Search): those whose name holds one of its words and whose name, namespace or summary holds every one, best named first. | |
| searchWords($query) | The words of a query: white space separates them, and quotes around one are ignored -- quotes are how a search engine is asked for a phrase, and here the exact phrase ranks first anyway (self:… | |
| symbolDocumentation($entry, $line) | Where a documentation index entry is documented, and what it says. | |
| symbolLinks($name) | ||
| testClassFor($class) | The test class conventionally matching $class: tests inserted right after its package's namespace. | |
| textResult($text, $isError) | ||
| toolDescribeClass($args) | ||
| toolDescribeFunction($args) | ||
| toolDocumentationIndex($args) | ||
| toolGenerateControllerStub($args) | ||
| toolGenerateEntityStub($args) | ||
| toolGenerateTestStub($args) | ||
| toolGetEntitySchema($args) | ||
| toolListEntities($args) | ||
| toolListFunctions($args) | ||
| toolListPackages($args) | ||
| toolListRoutes($args) | ||
| toolSearchDocumentation($args) | ||
| toolValidateSchema($args) |
Constants20
DOC_INDEX
ERROR_INTERNAL
ERROR_INVALID_PARAMS
ERROR_INVALID_REQUEST
ERROR_METHOD_NOT_FOUND
ERROR_PARSE
GUIDE
The full coding guide: also served verbatim as initialize's instructions and as the mmoframework://guide resource. Kept as a single source of truth on purpose.
INDEX_LIMIT
JSONRPC_VERSION
LATEST_PROTOCOL_VERSION
PROMPTS
Every prompt this server exposes through prompts/list/prompts/get.
SEARCH_LIMIT
SEARCH_STOPWORDS
The words a relaxed search drops first, whatever their frequency: a question asks with them, documentation is not written with them, and how common they are here says nothing about that. new is in half the documentation because php spells an instance that way, and how in a quarter of it -- dropping how first is what a reader means. self::searchRelaxed. They are never dropped from a search that matches whole.
SEARCH_WINDOW
SECTION_CHARS
SECTION_LINES
SECTION_MATCHES
How many of the best matches come back with the whole section holding them, and how much of one is worth returning. An agent answers from what a search gives it: over an evaluation run it called search_documentation 75 times and read a page in full twice, so an excerpt that only looks like an answer becomes a wrong answer.
SUPPORTED_PROTOCOL_VERSIONS
SYMBOL_LIMIT
TOOLS
Every tool this server exposes through tools/list/tools/call.
Properties1
discovered
- Type
- bool
Methods53
dataListEntities($repositoryFilter)
MCPController.php:1463dataListFunctions($namespace)
MCPController.php:1528dataListPackages()
MCPController.php:1505| returns | array | [name, title, version, included, namespace, description, status, keywords, dependencies, documentation, links] the PackageManifest showcase metadata of every package this server documents (getPackages). |
dataListRoutes($controllerFilter)
MCPController.php:1485describeParameterDocs($fn)
MCPController.php:1623What each parameter's @param says: an options class (PrintOptions) explains its options there.
| $fn | ReflectionFunctionAbstract | |
| returns | array | string> parameter name => its description (its type left out) |
describeParameters($fn)
MCPController.php:1632| $fn | ReflectionFunctionAbstract | |
| returns | string |
discoverDocuments()
MCPController.php:1573| returns | array | [uri, path, package, included, title] every *.md doc file of every documented package's (getPackages) documentations folders and agent skills. |
discoverRepositories()
MCPController.php:1448| returns | array | [iRepository] every repository exposed by a connected controller's getRepositories(). |
dispatchMethod($method, $params)
MCPController.php:551documentedPackages()
MCPController.php:1286| returns | array | true> the names of the packages this server documents (self::getPackages()) |
documentedSymbol($name)
MCPController.php:1236| $name | string | a fully-qualified name, as the documentation index keys it |
| returns | null | array | mixed>|null mmo.doc's index entry for it (DocIndex::Load), when mmo.doc is loaded, it is documented, and its package is one this server documents |
documentPaths()
MCPController.php:1291| returns | array | string> uri => filename of every mmoframework-docs:// resource (self::discoverDocuments()), read once per request |
getPackages()
MCPController.php:1555The packages this server documents: every included one, then, with $discovered, every other package PackageManager read the manifest of (its most recent version), by name. Included ones come first: a search ranks equal matches in this order.
| returns | array |
mcpInitialize($params)
MCPController.php:576mcpPromptsGet($params)
MCPController.php:1381mcpPromptsList($params)
MCPController.php:1373mcpResourcesList($params)
MCPController.php:1322mcpResourcesRead($params)
MCPController.php:1343mcpToolsCall($params)
MCPController.php:609mcpToolsList($params)
MCPController.php:594onRoute($route)
MCPController.php:493promptCreateController($args)
MCPController.php:1422promptCreateEntity($args)
MCPController.php:1398resourceContents($uri, $mimeType, $text)
MCPController.php:1367routeMCP($route)
MCPController.php:505routeStream($route)
MCPController.php:540rpcError($id, $code, $message)
MCPController.php:570rpcResult($id, $result)
MCPController.php:566searchDocuments($documents, $query, $missing)
MCPController.php:1031searchLines($lines, $words)
MCPController.php:1066Where $lines hold every one of $words: each line holding them all, or else the fewest consecutive lines (at most SEARCH_WINDOW) holding them together. Such windows never overlap, nor include a line that matches on its own.
| $lines | array | |
| $words | array | |
| returns | array | int}> the index of the first and of the last line of each match, in the order of $lines |
searchRank($excerpt, $oneLine, $words, $phrase)
MCPController.php:1103What ranks a match of searchDocuments(), lowest first: its tier (0 when it holds the exact phrase, 1 when it is a single line, 2 when its words spread over several), then how many words it only finds inside another word (entity in identity, unlike Repository in JsonRepository), then the length of the shortest stretch of it holding every word. The phrase only counts where a word starts too: get entity is not in target entity.
| $excerpt | string | the text matched |
| $oneLine | bool | whether it is a single line |
| $words | array | |
| $phrase | string | the words, as the query gave them |
| returns | array | int, int} |
searchRelaxed($documents, $query, $package)
MCPController.php:1006What a query matches when no line holds all of it: its most common words are dropped, one at a time, until something matches. A wrong guess at a name then still finds the page holding the rest of it, rather than nothing at all -- one word too many in a guessed command used to hide the page that names the real one.
searchSection($lines, $at)
MCPController.php:960The markdown section holding line $at: from the heading above it down to the next heading of the same level or higher, a deeper one belonging to it. Without a heading above, the section starts at the first line and any heading ends it.
| $lines | array | |
| $at | int | the index of the line the section must hold |
| returns | array | int, string} the first and last line of the section, and the text of its heading ('' when none) |
searchSections($matches, $documents)
MCPController.php:918The matches, the best few carrying the whole markdown section holding them: its heading, and its lines down to the next heading of the same level or higher. A search excerpt is three lines at most, which is enough to look like an answer and not enough to be one -- and the follow-up read that would settle it is the call an agent does not make. Only the first SECTION_MATCHES distinct sections are given; the rest stay excerpts.
searchSymbols($query, $package)
MCPController.php:1131The documented symbols a query names (DocIndex::Search): those whose name holds one of its words and whose name, namespace or summary holds every one, best named first. Nothing when mmo.doc is not loaded.
| $query | string | |
| $package = '' | string | only this package's, or every documented package's when '' |
| returns | array | ?string, line: int, excerpt: string, symbol: string, kind: string, language: string, package: ?string, url: ?string}> at most SYMBOL_LIMIT |
searchWords($query)
MCPController.php:984The words of a query: white space separates them, and quotes around one are ignored -- quotes are how a search engine is asked for a phrase, and here the exact phrase ranks first anyway (self::searchRank).
symbolDocumentation($entry, $line)
MCPController.php:1258Where a documentation index entry is documented, and what it says.
symbolLinks($name)
MCPController.php:1245| $name | string | |
| returns | array | string, resource?: string, line?: int} where $name is documented (self::symbolDocumentation()), or [] |
testClassFor($class)
MCPController.php:807The test class conventionally matching $class: tests inserted right after its package's namespace.
textResult($text, $isError)
MCPController.php:625toolDescribeClass($args)
MCPController.php:631toolDescribeFunction($args)
MCPController.php:729toolDocumentationIndex($args)
MCPController.php:1177toolGenerateControllerStub($args)
MCPController.php:770toolGenerateEntityStub($args)
MCPController.php:748toolGenerateTestStub($args)
MCPController.php:791toolGetEntitySchema($args)
MCPController.php:706toolListEntities($args)
MCPController.php:697toolListFunctions($args)
MCPController.php:722toolListPackages($args)
MCPController.php:1301toolListRoutes($args)
MCPController.php:717toolSearchDocumentation($args)
MCPController.php:848toolValidateSchema($args)
MCPController.php:823Inherited members (55)
| Constants | Declared by | Description | |
|---|---|---|---|
ALERT | iLogLevel | Alert: Action must be taken immediately. | |
ALL | iLogLevel | Mask for all | |
ALL_PLUS | iLogLevel | debug everything | |
BACKTRACE | iLogLevel | ||
CRITICAL | iLogLevel | Critical: Critical conditions. | |
DEBUG | iLogLevel | Debug: Detailed debug information. | |
DEEP | iLogLevel | debug everything with arguments | |
EMERGENCY | iLogLevel | Emergency: System is unusable. | |
ERROR | iLogLevel | Error: Runtime errors that do not require immediate action but should typically be logged and monitored. | |
ERROR_PLUS | iLogLevel | Mask for all error | |
FATAL | iLogLevel | Mask for all fatal error | |
INFO | iLogLevel | Info: Interesting events. | |
INFO_PLUS | iLogLevel | Mask for all errors/warning/notices/info | |
MEMORY | iLogLevel | include backtrace object | |
NOTICE | iLogLevel | Notice: Normal but significant events. | |
NOTICE_PLUS | iLogLevel | Mask for all errors/warning/notices/info | |
TRACE | iLogLevel | include backtrace as origins | |
WARNING | iLogLevel | Warning: Exceptional occurrences that are not errors. | |
WARNING_PLUS | iLogLevel | Mask for all errors and warnings |
| Properties | Declared by | Description | |
|---|---|---|---|
verbosity | aModule |
| Methods | Declared by | Description | |
|---|---|---|---|
alert($message, $context) | aModule | Action must be taken immediately. | |
backtraces($message, $context) | aModule | Force-log a message at INFO level together with a full stack trace/memory snapshot (iLogLevel::BACKTRACE), bypassing the verbosity mask entirely (any non-zero verbosity is enough to trigger it). | |
Configure($config) | aModule | Merge $config into this module's configuration in the shared Configuration. | |
critical($message, $context) | aModule | Critical conditions. No-op if CRITICAL is currently filtered out by the verbosity mask. | |
debug($message, $context) | aModule | Detailed debug information. | |
debugName() | aModule | Human-readable identifier used as the default {origin} in this instance's log messages. | |
DefaultConfig() | aModule | The config a module starts from before anything loaded via Configuration is merged in. | |
emergency($message, $context) | aModule | System is unusable. No-op if EMERGENCY is currently filtered out by the verbosity mask. | |
error($message, $context) | aModule | Runtime errors that do not require immediate action but should typically be logged and monitored. | |
ExtractRoutes($config) | aController | Extract all the APIRoute from this class, regardless of the fact they are registered in the application | |
getVerbosity() | aModule | ||
HasRoutes() | aController | Tells if any APIRoute are registered in the application | |
info($message, $context) | aModule | Interesting events. No-op if INFO is currently filtered out by the verbosity mask. | |
Instantiate($config) | aModule | (Re)create the shared instance immediately, configured with $config merged into the class's existing config. | |
IsShared() | aModule | ||
Link($method, $data) | aController | Build a Link (URL + label/icon/description/title, taken from the route's APIRoute metadata) for a registered route. | |
log($level, $message, $context) | aModule | Logs with an arbitrary level. | |
notice($message, $context) | aModule | Normal but significant events. | |
offsetExists($key) | aModule | \ArrayAccess::offsetExists -- tells whether $key is a declared property at all, regardless of whether it is currently readable/writable through array access. | |
offsetGet($key) | aModule | \ArrayAccess::offsetGet -- reads a property directly, unless it has a #[Serialize(serialize: 'methodName')] attribute, in which case that zero-argument method is called instead (e.g. | |
offsetSet($key, $value) | aModule | \ArrayAccess::offsetSet -- sets a property directly, unless it has a #[Serialize(unserialize: 'methodName')] attribute, in which case that method is called with $value instead (e.g. | |
offsetUnset($key) | aModule | \ArrayAccess::offsetUnset -- equivalent to $module[$key] = null. | |
Route($method) | aController | Get a registered APIRoute WARNING: if this class was not registered in the application, it will return null. | |
Routes() | aController | Get a list of registered APIRoutes (from this class) in the application WARNING: if this class was not registered in the application, it will return an empty array. | |
serialize($path, $serializer) | aModule | \MMO\core\interfaces\iSerializable::serialize -- exports every property (via | |
setVerbosity($verb) | aModule | Set the current verbosity mask, replacing whatever it was before. | |
Shared() | aModule | Get the shared instance, creating (and configuring) it on first call. | |
testVerbosity($level) | aModule | Test whether a given level (or set of levels) is currently enabled by this instance's verbosity mask. | |
traitUnshare($serialize) | aModule | Remove the shared instance, so the next Shared() call creates a fresh one. | |
unserialize($data, $path, $instances) | aModule | \MMO\core\interfaces\iSerializable::unserialize -- merges $data onto DefaultConfig, runs it through the (possibly overridden) constructor, then applies each resulting value to its property (via | |
Unshare($serialize) | aModule | Like tSingleton::Unshare, but also disconnects this module's instance from every event it was listening to (via Event::DisconnectListeners) before dropping it. | |
Url($method, $data) | aController | Build the URL for a registered route, filling in any {placeholder} from $data. | |
warning($message, $context) | aModule | Exceptional occurrences that are not errors. | |
__construct($config) | aModule | protected constructor, so it is not possible to do new Module(...) called by the serialization process just before being injected with data. | |
__wakeup() | aController | Called automatically right after the controller's shared instance is built (aModule::unserialize): registers onRoute as a Route listener with a low priority (-10), so it… |