# Directory Structure
```
├── build
│ ├── CacheManager.d.ts
│ ├── CacheManager.js
│ ├── index.d.ts
│ ├── index.js
│ ├── types.d.ts
│ └── types.js
├── config.json
├── Dockerfile
├── node_modules
│ ├── .bin
│ │ ├── tsc
│ │ └── tsserver
│ ├── .package-lock.json
│ ├── @modelcontextprotocol
│ │ └── sdk
│ │ ├── dist
│ │ │ ├── cli.d.ts
│ │ │ ├── cli.d.ts.map
│ │ │ ├── cli.js
│ │ │ ├── cli.js.map
│ │ │ ├── client
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── index.test.d.ts
│ │ │ │ ├── index.test.d.ts.map
│ │ │ │ ├── index.test.js
│ │ │ │ ├── index.test.js.map
│ │ │ │ ├── sse.d.ts
│ │ │ │ ├── sse.d.ts.map
│ │ │ │ ├── sse.js
│ │ │ │ ├── sse.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ ├── stdio.js.map
│ │ │ │ ├── stdio.test.d.ts
│ │ │ │ ├── stdio.test.d.ts.map
│ │ │ │ ├── stdio.test.js
│ │ │ │ ├── stdio.test.js.map
│ │ │ │ ├── websocket.d.ts
│ │ │ │ ├── websocket.d.ts.map
│ │ │ │ ├── websocket.js
│ │ │ │ └── websocket.js.map
│ │ │ ├── inMemory.d.ts
│ │ │ ├── inMemory.d.ts.map
│ │ │ ├── inMemory.js
│ │ │ ├── inMemory.js.map
│ │ │ ├── inMemory.test.d.ts
│ │ │ ├── inMemory.test.d.ts.map
│ │ │ ├── inMemory.test.js
│ │ │ ├── inMemory.test.js.map
│ │ │ ├── server
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── index.test.d.ts
│ │ │ │ ├── index.test.d.ts.map
│ │ │ │ ├── index.test.js
│ │ │ │ ├── index.test.js.map
│ │ │ │ ├── sse.d.ts
│ │ │ │ ├── sse.d.ts.map
│ │ │ │ ├── sse.js
│ │ │ │ ├── sse.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ ├── stdio.js.map
│ │ │ │ ├── stdio.test.d.ts
│ │ │ │ ├── stdio.test.d.ts.map
│ │ │ │ ├── stdio.test.js
│ │ │ │ └── stdio.test.js.map
│ │ │ ├── shared
│ │ │ │ ├── protocol.d.ts
│ │ │ │ ├── protocol.d.ts.map
│ │ │ │ ├── protocol.js
│ │ │ │ ├── protocol.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ ├── stdio.js.map
│ │ │ │ ├── stdio.test.d.ts
│ │ │ │ ├── stdio.test.d.ts.map
│ │ │ │ ├── stdio.test.js
│ │ │ │ ├── stdio.test.js.map
│ │ │ │ ├── transport.d.ts
│ │ │ │ ├── transport.d.ts.map
│ │ │ │ ├── transport.js
│ │ │ │ └── transport.js.map
│ │ │ ├── types.d.ts
│ │ │ ├── types.d.ts.map
│ │ │ ├── types.js
│ │ │ └── types.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── @types
│ │ ├── fs-extra
│ │ │ ├── esm.d.mts
│ │ │ ├── index.d.ts
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── README.md
│ │ ├── jsonfile
│ │ │ ├── index.d.ts
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ ├── README.md
│ │ │ └── utils.d.ts
│ │ └── node
│ │ ├── assert
│ │ │ └── strict.d.ts
│ │ ├── assert.d.ts
│ │ ├── async_hooks.d.ts
│ │ ├── buffer.buffer.d.ts
│ │ ├── buffer.d.ts
│ │ ├── child_process.d.ts
│ │ ├── cluster.d.ts
│ │ ├── compatibility
│ │ │ ├── disposable.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── indexable.d.ts
│ │ │ └── iterators.d.ts
│ │ ├── console.d.ts
│ │ ├── constants.d.ts
│ │ ├── crypto.d.ts
│ │ ├── dgram.d.ts
│ │ ├── diagnostics_channel.d.ts
│ │ ├── dns
│ │ │ └── promises.d.ts
│ │ ├── dns.d.ts
│ │ ├── dom-events.d.ts
│ │ ├── domain.d.ts
│ │ ├── events.d.ts
│ │ ├── fs
│ │ │ └── promises.d.ts
│ │ ├── fs.d.ts
│ │ ├── globals.d.ts
│ │ ├── globals.typedarray.d.ts
│ │ ├── http.d.ts
│ │ ├── http2.d.ts
│ │ ├── https.d.ts
│ │ ├── index.d.ts
│ │ ├── inspector.d.ts
│ │ ├── LICENSE
│ │ ├── module.d.ts
│ │ ├── net.d.ts
│ │ ├── os.d.ts
│ │ ├── package.json
│ │ ├── path.d.ts
│ │ ├── perf_hooks.d.ts
│ │ ├── process.d.ts
│ │ ├── punycode.d.ts
│ │ ├── querystring.d.ts
│ │ ├── readline
│ │ │ └── promises.d.ts
│ │ ├── readline.d.ts
│ │ ├── README.md
│ │ ├── repl.d.ts
│ │ ├── sea.d.ts
│ │ ├── stream
│ │ │ ├── consumers.d.ts
│ │ │ ├── promises.d.ts
│ │ │ └── web.d.ts
│ │ ├── stream.d.ts
│ │ ├── string_decoder.d.ts
│ │ ├── test.d.ts
│ │ ├── timers
│ │ │ └── promises.d.ts
│ │ ├── timers.d.ts
│ │ ├── tls.d.ts
│ │ ├── trace_events.d.ts
│ │ ├── ts5.6
│ │ │ ├── buffer.buffer.d.ts
│ │ │ ├── globals.typedarray.d.ts
│ │ │ └── index.d.ts
│ │ ├── tty.d.ts
│ │ ├── url.d.ts
│ │ ├── util.d.ts
│ │ ├── v8.d.ts
│ │ ├── vm.d.ts
│ │ ├── wasi.d.ts
│ │ ├── worker_threads.d.ts
│ │ └── zlib.d.ts
│ ├── bytes
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── content-type
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── depd
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ └── browser
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── fs-extra
│ │ ├── lib
│ │ │ ├── copy
│ │ │ │ ├── copy-sync.js
│ │ │ │ ├── copy.js
│ │ │ │ └── index.js
│ │ │ ├── empty
│ │ │ │ └── index.js
│ │ │ ├── ensure
│ │ │ │ ├── file.js
│ │ │ │ ├── index.js
│ │ │ │ ├── link.js
│ │ │ │ ├── symlink-paths.js
│ │ │ │ ├── symlink-type.js
│ │ │ │ └── symlink.js
│ │ │ ├── esm.mjs
│ │ │ ├── fs
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ ├── json
│ │ │ │ ├── index.js
│ │ │ │ ├── jsonfile.js
│ │ │ │ ├── output-json-sync.js
│ │ │ │ └── output-json.js
│ │ │ ├── mkdirs
│ │ │ │ ├── index.js
│ │ │ │ ├── make-dir.js
│ │ │ │ └── utils.js
│ │ │ ├── move
│ │ │ │ ├── index.js
│ │ │ │ ├── move-sync.js
│ │ │ │ └── move.js
│ │ │ ├── output-file
│ │ │ │ └── index.js
│ │ │ ├── path-exists
│ │ │ │ └── index.js
│ │ │ ├── remove
│ │ │ │ └── index.js
│ │ │ └── util
│ │ │ ├── stat.js
│ │ │ └── utimes.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── graceful-fs
│ │ ├── clone.js
│ │ ├── graceful-fs.js
│ │ ├── legacy-streams.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── polyfills.js
│ │ └── README.md
│ ├── http-errors
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── iconv-lite
│ │ ├── .github
│ │ │ └── dependabot.yml
│ │ ├── .idea
│ │ │ ├── codeStyles
│ │ │ │ ├── codeStyleConfig.xml
│ │ │ │ └── Project.xml
│ │ │ ├── iconv-lite.iml
│ │ │ ├── inspectionProfiles
│ │ │ │ └── Project_Default.xml
│ │ │ ├── modules.xml
│ │ │ └── vcs.xml
│ │ ├── Changelog.md
│ │ ├── encodings
│ │ │ ├── dbcs-codec.js
│ │ │ ├── dbcs-data.js
│ │ │ ├── index.js
│ │ │ ├── internal.js
│ │ │ ├── sbcs-codec.js
│ │ │ ├── sbcs-data-generated.js
│ │ │ ├── sbcs-data.js
│ │ │ ├── tables
│ │ │ │ ├── big5-added.json
│ │ │ │ ├── cp936.json
│ │ │ │ ├── cp949.json
│ │ │ │ ├── cp950.json
│ │ │ │ ├── eucjp.json
│ │ │ │ ├── gb18030-ranges.json
│ │ │ │ ├── gbk-added.json
│ │ │ │ └── shiftjis.json
│ │ │ ├── utf16.js
│ │ │ ├── utf32.js
│ │ │ └── utf7.js
│ │ ├── lib
│ │ │ ├── bom-handling.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── streams.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── inherits
│ │ ├── inherits_browser.js
│ │ ├── inherits.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── jsonfile
│ │ ├── CHANGELOG.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── utils.js
│ ├── raw-body
│ │ ├── HISTORY.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── safer-buffer
│ │ ├── dangerous.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── Porting-Buffer.md
│ │ ├── Readme.md
│ │ ├── safer.js
│ │ └── tests.js
│ ├── setprototypeof
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── test
│ │ └── index.js
│ ├── statuses
│ │ ├── codes.json
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── toidentifier
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── typescript
│ │ ├── bin
│ │ │ ├── tsc
│ │ │ └── tsserver
│ │ ├── lib
│ │ │ ├── _tsc.js
│ │ │ ├── _tsserver.js
│ │ │ ├── _typingsInstaller.js
│ │ │ ├── cancellationToken.js
│ │ │ ├── cs
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── de
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── es
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── fr
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── it
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── ja
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── ko
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── lib.d.ts
│ │ │ ├── lib.decorators.d.ts
│ │ │ ├── lib.decorators.legacy.d.ts
│ │ │ ├── lib.dom.asynciterable.d.ts
│ │ │ ├── lib.dom.d.ts
│ │ │ ├── lib.dom.iterable.d.ts
│ │ │ ├── lib.es2015.collection.d.ts
│ │ │ ├── lib.es2015.core.d.ts
│ │ │ ├── lib.es2015.d.ts
│ │ │ ├── lib.es2015.generator.d.ts
│ │ │ ├── lib.es2015.iterable.d.ts
│ │ │ ├── lib.es2015.promise.d.ts
│ │ │ ├── lib.es2015.proxy.d.ts
│ │ │ ├── lib.es2015.reflect.d.ts
│ │ │ ├── lib.es2015.symbol.d.ts
│ │ │ ├── lib.es2015.symbol.wellknown.d.ts
│ │ │ ├── lib.es2016.array.include.d.ts
│ │ │ ├── lib.es2016.d.ts
│ │ │ ├── lib.es2016.full.d.ts
│ │ │ ├── lib.es2016.intl.d.ts
│ │ │ ├── lib.es2017.arraybuffer.d.ts
│ │ │ ├── lib.es2017.d.ts
│ │ │ ├── lib.es2017.date.d.ts
│ │ │ ├── lib.es2017.full.d.ts
│ │ │ ├── lib.es2017.intl.d.ts
│ │ │ ├── lib.es2017.object.d.ts
│ │ │ ├── lib.es2017.sharedmemory.d.ts
│ │ │ ├── lib.es2017.string.d.ts
│ │ │ ├── lib.es2017.typedarrays.d.ts
│ │ │ ├── lib.es2018.asyncgenerator.d.ts
│ │ │ ├── lib.es2018.asynciterable.d.ts
│ │ │ ├── lib.es2018.d.ts
│ │ │ ├── lib.es2018.full.d.ts
│ │ │ ├── lib.es2018.intl.d.ts
│ │ │ ├── lib.es2018.promise.d.ts
│ │ │ ├── lib.es2018.regexp.d.ts
│ │ │ ├── lib.es2019.array.d.ts
│ │ │ ├── lib.es2019.d.ts
│ │ │ ├── lib.es2019.full.d.ts
│ │ │ ├── lib.es2019.intl.d.ts
│ │ │ ├── lib.es2019.object.d.ts
│ │ │ ├── lib.es2019.string.d.ts
│ │ │ ├── lib.es2019.symbol.d.ts
│ │ │ ├── lib.es2020.bigint.d.ts
│ │ │ ├── lib.es2020.d.ts
│ │ │ ├── lib.es2020.date.d.ts
│ │ │ ├── lib.es2020.full.d.ts
│ │ │ ├── lib.es2020.intl.d.ts
│ │ │ ├── lib.es2020.number.d.ts
│ │ │ ├── lib.es2020.promise.d.ts
│ │ │ ├── lib.es2020.sharedmemory.d.ts
│ │ │ ├── lib.es2020.string.d.ts
│ │ │ ├── lib.es2020.symbol.wellknown.d.ts
│ │ │ ├── lib.es2021.d.ts
│ │ │ ├── lib.es2021.full.d.ts
│ │ │ ├── lib.es2021.intl.d.ts
│ │ │ ├── lib.es2021.promise.d.ts
│ │ │ ├── lib.es2021.string.d.ts
│ │ │ ├── lib.es2021.weakref.d.ts
│ │ │ ├── lib.es2022.array.d.ts
│ │ │ ├── lib.es2022.d.ts
│ │ │ ├── lib.es2022.error.d.ts
│ │ │ ├── lib.es2022.full.d.ts
│ │ │ ├── lib.es2022.intl.d.ts
│ │ │ ├── lib.es2022.object.d.ts
│ │ │ ├── lib.es2022.regexp.d.ts
│ │ │ ├── lib.es2022.string.d.ts
│ │ │ ├── lib.es2023.array.d.ts
│ │ │ ├── lib.es2023.collection.d.ts
│ │ │ ├── lib.es2023.d.ts
│ │ │ ├── lib.es2023.full.d.ts
│ │ │ ├── lib.es2023.intl.d.ts
│ │ │ ├── lib.es2024.arraybuffer.d.ts
│ │ │ ├── lib.es2024.collection.d.ts
│ │ │ ├── lib.es2024.d.ts
│ │ │ ├── lib.es2024.full.d.ts
│ │ │ ├── lib.es2024.object.d.ts
│ │ │ ├── lib.es2024.promise.d.ts
│ │ │ ├── lib.es2024.regexp.d.ts
│ │ │ ├── lib.es2024.sharedmemory.d.ts
│ │ │ ├── lib.es2024.string.d.ts
│ │ │ ├── lib.es5.d.ts
│ │ │ ├── lib.es6.d.ts
│ │ │ ├── lib.esnext.array.d.ts
│ │ │ ├── lib.esnext.collection.d.ts
│ │ │ ├── lib.esnext.d.ts
│ │ │ ├── lib.esnext.decorators.d.ts
│ │ │ ├── lib.esnext.disposable.d.ts
│ │ │ ├── lib.esnext.full.d.ts
│ │ │ ├── lib.esnext.intl.d.ts
│ │ │ ├── lib.esnext.iterator.d.ts
│ │ │ ├── lib.scripthost.d.ts
│ │ │ ├── lib.webworker.asynciterable.d.ts
│ │ │ ├── lib.webworker.d.ts
│ │ │ ├── lib.webworker.importscripts.d.ts
│ │ │ ├── lib.webworker.iterable.d.ts
│ │ │ ├── pl
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── pt-br
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── ru
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── tr
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ ├── tsc.js
│ │ │ ├── tsserver.js
│ │ │ ├── tsserverlibrary.d.ts
│ │ │ ├── tsserverlibrary.js
│ │ │ ├── typescript.d.ts
│ │ │ ├── typescript.js
│ │ │ ├── typesMap.json
│ │ │ ├── typingsInstaller.js
│ │ │ ├── watchGuard.js
│ │ │ ├── zh-cn
│ │ │ │ └── diagnosticMessages.generated.json
│ │ │ └── zh-tw
│ │ │ └── diagnosticMessages.generated.json
│ │ ├── LICENSE.txt
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── SECURITY.md
│ │ └── ThirdPartyNoticeText.txt
│ ├── undici-types
│ │ ├── agent.d.ts
│ │ ├── api.d.ts
│ │ ├── balanced-pool.d.ts
│ │ ├── cache.d.ts
│ │ ├── client.d.ts
│ │ ├── connector.d.ts
│ │ ├── content-type.d.ts
│ │ ├── cookies.d.ts
│ │ ├── diagnostics-channel.d.ts
│ │ ├── dispatcher.d.ts
│ │ ├── env-http-proxy-agent.d.ts
│ │ ├── errors.d.ts
│ │ ├── eventsource.d.ts
│ │ ├── fetch.d.ts
│ │ ├── file.d.ts
│ │ ├── filereader.d.ts
│ │ ├── formdata.d.ts
│ │ ├── global-dispatcher.d.ts
│ │ ├── global-origin.d.ts
│ │ ├── handlers.d.ts
│ │ ├── header.d.ts
│ │ ├── index.d.ts
│ │ ├── interceptors.d.ts
│ │ ├── LICENSE
│ │ ├── mock-agent.d.ts
│ │ ├── mock-client.d.ts
│ │ ├── mock-errors.d.ts
│ │ ├── mock-interceptor.d.ts
│ │ ├── mock-pool.d.ts
│ │ ├── package.json
│ │ ├── patch.d.ts
│ │ ├── pool-stats.d.ts
│ │ ├── pool.d.ts
│ │ ├── proxy-agent.d.ts
│ │ ├── readable.d.ts
│ │ ├── README.md
│ │ ├── retry-agent.d.ts
│ │ ├── retry-handler.d.ts
│ │ ├── util.d.ts
│ │ ├── webidl.d.ts
│ │ └── websocket.d.ts
│ ├── universalify
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── unpipe
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ └── zod
│ ├── index.d.ts
│ ├── lib
│ │ ├── __tests__
│ │ │ ├── Mocker.d.ts
│ │ │ └── Mocker.js
│ │ ├── benchmarks
│ │ │ ├── datetime.d.ts
│ │ │ ├── datetime.js
│ │ │ ├── discriminatedUnion.d.ts
│ │ │ ├── discriminatedUnion.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── ipv4.d.ts
│ │ │ ├── ipv4.js
│ │ │ ├── object.d.ts
│ │ │ ├── object.js
│ │ │ ├── primitives.d.ts
│ │ │ ├── primitives.js
│ │ │ ├── realworld.d.ts
│ │ │ ├── realworld.js
│ │ │ ├── string.d.ts
│ │ │ ├── string.js
│ │ │ ├── union.d.ts
│ │ │ └── union.js
│ │ ├── errors.d.ts
│ │ ├── errors.js
│ │ ├── external.d.ts
│ │ ├── external.js
│ │ ├── helpers
│ │ │ ├── enumUtil.d.ts
│ │ │ ├── enumUtil.js
│ │ │ ├── errorUtil.d.ts
│ │ │ ├── errorUtil.js
│ │ │ ├── parseUtil.d.ts
│ │ │ ├── parseUtil.js
│ │ │ ├── partialUtil.d.ts
│ │ │ ├── partialUtil.js
│ │ │ ├── typeAliases.d.ts
│ │ │ ├── typeAliases.js
│ │ │ ├── util.d.ts
│ │ │ └── util.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.mjs
│ │ ├── index.umd.js
│ │ ├── locales
│ │ │ ├── en.d.ts
│ │ │ └── en.js
│ │ ├── standard-schema.d.ts
│ │ ├── standard-schema.js
│ │ ├── types.d.ts
│ │ ├── types.js
│ │ ├── ZodError.d.ts
│ │ └── ZodError.js
│ ├── LICENSE
│ ├── package.json
│ └── README.md
├── package-lock.json
├── package.json
├── project.md
├── README.md
├── smithery.yaml
├── src
│ ├── CacheManager.ts
│ ├── index.ts
│ └── types.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Memory Cache Server
2 | [](https://smithery.ai/server/@tosin2013/mcp-memory-cache-server)
3 |
4 | A Model Context Protocol (MCP) server that reduces token consumption by efficiently caching data between language model interactions. Works with any MCP client and any language model that uses tokens.
5 |
6 | ## Installation
7 |
8 | ### Installing via Smithery
9 |
10 | To install Memory Cache Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@tosin2013/mcp-memory-cache-server):
11 |
12 | ```bash
13 | npx -y @smithery/cli install @tosin2013/mcp-memory-cache-server --client claude
14 | ```
15 |
16 | ### Installing Manually
17 | 1. Clone the repository:
18 | ```bash
19 | git clone https://github.com/tosin2013/mcp-memory-cache-server.git
20 | cd mcp-memory-cache-server
21 | ```
22 |
23 | 2. Install dependencies:
24 | ```bash
25 | npm install
26 | ```
27 |
28 | 3. Build the project:
29 | ```bash
30 | npm run build
31 | ```
32 |
33 | 4. Add to your MCP client settings:
34 | ```json
35 | {
36 | "mcpServers": {
37 | "memory-cache": {
38 | "command": "node",
39 | "args": ["/path/to/ib-mcp-cache-server/build/index.js"]
40 | }
41 | }
42 | }
43 | ```
44 |
45 | 5. The server will automatically start when you use your MCP client
46 |
47 | ## Verifying It Works
48 |
49 | When the server is running properly, you'll see:
50 | 1. A message in the terminal: "Memory Cache MCP server running on stdio"
51 | 2. Improved performance when accessing the same data multiple times
52 | 3. No action required from you - the caching happens automatically
53 |
54 | You can verify the server is running by:
55 | 1. Opening your MCP client
56 | 2. Looking for any error messages in the terminal where you started the server
57 | 3. Performing operations that would benefit from caching (like reading the same file multiple times)
58 |
59 | ## Configuration
60 |
61 | The server can be configured through `config.json` or environment variables:
62 |
63 | ```json
64 | {
65 | "maxEntries": 1000, // Maximum number of items in cache
66 | "maxMemory": 104857600, // Maximum memory usage in bytes (100MB)
67 | "defaultTTL": 3600, // Default time-to-live in seconds (1 hour)
68 | "checkInterval": 60000, // Cleanup interval in milliseconds (1 minute)
69 | "statsInterval": 30000 // Stats update interval in milliseconds (30 seconds)
70 | }
71 | ```
72 |
73 | ### Configuration Settings Explained
74 |
75 | 1. **maxEntries** (default: 1000)
76 | - Maximum number of items that can be stored in cache
77 | - Prevents cache from growing indefinitely
78 | - When exceeded, oldest unused items are removed first
79 |
80 | 2. **maxMemory** (default: 100MB)
81 | - Maximum memory usage in bytes
82 | - Prevents excessive memory consumption
83 | - When exceeded, least recently used items are removed
84 |
85 | 3. **defaultTTL** (default: 1 hour)
86 | - How long items stay in cache by default
87 | - Items are automatically removed after this time
88 | - Prevents stale data from consuming memory
89 |
90 | 4. **checkInterval** (default: 1 minute)
91 | - How often the server checks for expired items
92 | - Lower values keep memory usage more accurate
93 | - Higher values reduce CPU usage
94 |
95 | 5. **statsInterval** (default: 30 seconds)
96 | - How often cache statistics are updated
97 | - Affects accuracy of hit/miss rates
98 | - Helps monitor cache effectiveness
99 |
100 | ## How It Reduces Token Consumption
101 |
102 | The memory cache server reduces token consumption by automatically storing data that would otherwise need to be re-sent between you and the language model. You don't need to do anything special - the caching happens automatically when you interact with any language model through your MCP client.
103 |
104 | Here are some examples of what gets cached:
105 |
106 | ### 1. File Content Caching
107 | When reading a file multiple times:
108 | - First time: Full file content is read and cached
109 | - Subsequent times: Content is retrieved from cache instead of re-reading the file
110 | - Result: Fewer tokens used for repeated file operations
111 |
112 | ### 2. Computation Results
113 | When performing calculations or analysis:
114 | - First time: Full computation is performed and results are cached
115 | - Subsequent times: Results are retrieved from cache if the input is the same
116 | - Result: Fewer tokens used for repeated computations
117 |
118 | ### 3. Frequently Accessed Data
119 | When the same data is needed multiple times:
120 | - First time: Data is processed and cached
121 | - Subsequent times: Data is retrieved from cache until TTL expires
122 | - Result: Fewer tokens used for accessing the same information
123 |
124 | ## Automatic Cache Management
125 |
126 | The server automatically manages the caching process by:
127 | - Storing data when first encountered
128 | - Serving cached data when available
129 | - Removing old/unused data based on settings
130 | - Tracking effectiveness through statistics
131 |
132 | ## Optimization Tips
133 |
134 | ### 1. Set Appropriate TTLs
135 | - Shorter for frequently changing data
136 | - Longer for static content
137 |
138 | ### 2. Adjust Memory Limits
139 | - Higher for more caching (more token savings)
140 | - Lower if memory usage is a concern
141 |
142 | ### 3. Monitor Cache Stats
143 | - High hit rate = good token savings
144 | - Low hit rate = adjust TTL or limits
145 |
146 | ## Environment Variable Configuration
147 |
148 | You can override config.json settings using environment variables in your MCP settings:
149 |
150 | ```json
151 | {
152 | "mcpServers": {
153 | "memory-cache": {
154 | "command": "node",
155 | "args": ["/path/to/build/index.js"],
156 | "env": {
157 | "MAX_ENTRIES": "5000",
158 | "MAX_MEMORY": "209715200", // 200MB
159 | "DEFAULT_TTL": "7200", // 2 hours
160 | "CHECK_INTERVAL": "120000", // 2 minutes
161 | "STATS_INTERVAL": "60000" // 1 minute
162 | }
163 | }
164 | }
165 | }
166 | ```
167 |
168 | You can also specify a custom config file location:
169 | ```json
170 | {
171 | "env": {
172 | "CONFIG_PATH": "/path/to/your/config.json"
173 | }
174 | }
175 | ```
176 |
177 | The server will:
178 | 1. Look for config.json in its directory
179 | 2. Apply any environment variable overrides
180 | 3. Use default values if neither is specified
181 |
182 | ## Testing the Cache in Practice
183 |
184 | To see the cache in action, try these scenarios:
185 |
186 | 1. **File Reading Test**
187 | - Read and analyze a large file
188 | - Ask the same question about the file again
189 | - The second response should be faster as the file content is cached
190 |
191 | 2. **Data Analysis Test**
192 | - Perform analysis on some data
193 | - Request the same analysis again
194 | - The second analysis should use cached results
195 |
196 | 3. **Project Navigation Test**
197 | - Explore a project's structure
198 | - Query the same files/directories again
199 | - Directory listings and file contents will be served from cache
200 |
201 | The cache is working when you notice:
202 | - Faster responses for repeated operations
203 | - Consistent answers about unchanged content
204 | - No need to re-read files that haven't changed
205 |
```
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "maxEntries": 1000,
3 | "maxMemory": 104857600,
4 | "defaultTTL": 3600,
5 | "checkInterval": 60000,
6 | "statsInterval": 30000
7 | }
8 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "module": "ES2020",
5 | "moduleResolution": "node",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "declaration": true
13 | },
14 | "include": ["src/**/*"],
15 | "exclude": ["node_modules", "build"]
16 | }
17 |
```
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
```typescript
1 | export interface CacheEntry {
2 | value: any;
3 | created: number;
4 | lastAccessed: number;
5 | ttl?: number;
6 | size: number;
7 | }
8 |
9 | export interface CacheStats {
10 | totalEntries: number;
11 | memoryUsage: number;
12 | hits: number;
13 | misses: number;
14 | hitRate: number;
15 | avgAccessTime: number;
16 | }
17 |
18 | export interface CacheConfig {
19 | maxEntries?: number;
20 | maxMemory?: number;
21 | defaultTTL?: number;
22 | checkInterval?: number;
23 | statsInterval?: number;
24 | }
25 |
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "charly-memory-cache-server",
3 | "version": "1.0.0",
4 | "description": "MCP server for memory caching and optimization",
5 | "type": "module",
6 | "main": "build/index.js",
7 | "scripts": {
8 | "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
9 | "start": "node build/index.js",
10 | "dev": "tsc -w",
11 | "prepare": "npm run build",
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "keywords": [
15 | "mcp",
16 | "cache",
17 | "memory",
18 | "optimization"
19 | ],
20 | "author": "",
21 | "license": "ISC",
22 | "devDependencies": {
23 | "@types/node": "^20.10.6",
24 | "@types/fs-extra": "^11.0.4",
25 | "typescript": "^5.3.3"
26 | },
27 | "dependencies": {
28 | "@modelcontextprotocol/sdk": "0.6.0",
29 | "fs-extra": "^11.2.0"
30 | }
31 | }
32 |
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
2 | # Use a Node.js image to build the project
3 | FROM node:18-alpine AS builder
4 |
5 | # Set the working directory inside the container
6 | WORKDIR /app
7 |
8 | # Copy the package.json and package-lock.json files
9 | COPY package.json package-lock.json ./
10 |
11 | # Install dependencies
12 | RUN npm install --ignore-scripts
13 |
14 | # Copy the rest of the project files
15 | COPY . .
16 |
17 | # Build the project
18 | RUN npm run build
19 |
20 | # Use a lighter Node.js image for the production stage
21 | FROM node:18-alpine
22 |
23 | # Set the working directory inside the container
24 | WORKDIR /app
25 |
26 | # Copy the built files and node_modules from the builder stage
27 | COPY --from=builder /app/build /app/build
28 | COPY --from=builder /app/node_modules /app/node_modules
29 | COPY --from=builder /app/package.json /app/package.json
30 |
31 | # Set the entry point to start the server
32 | ENTRYPOINT ["node", "build/index.js"]
33 |
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
2 |
3 | startCommand:
4 | type: stdio
5 | configSchema:
6 | # JSON Schema defining the configuration options for the MCP.
7 | type: object
8 | required:
9 | - maxEntries
10 | - maxMemory
11 | - defaultTTL
12 | - checkInterval
13 | - statsInterval
14 | properties:
15 | maxEntries:
16 | type: number
17 | description: Maximum number of items in cache
18 | maxMemory:
19 | type: number
20 | description: Maximum memory usage in bytes
21 | defaultTTL:
22 | type: number
23 | description: Default time-to-live for cached items in seconds
24 | checkInterval:
25 | type: number
26 | description: Interval for checking expired items in milliseconds
27 | statsInterval:
28 | type: number
29 | description: Interval for updating cache statistics in milliseconds
30 | commandFunction:
31 | # A function that produces the CLI command to start the MCP on stdio.
32 | |-
33 | (config) => ({ command: 'node', args: ['build/index.js'], env: { MAX_ENTRIES: String(config.maxEntries), MAX_MEMORY: String(config.maxMemory), DEFAULT_TTL: String(config.defaultTTL), CHECK_INTERVAL: String(config.checkInterval), STATS_INTERVAL: String(config.statsInterval) } })
34 |
```
--------------------------------------------------------------------------------
/project.md:
--------------------------------------------------------------------------------
```markdown
1 | # Charly Memory Cache Server - Technical Documentation
2 |
3 | Repository: [email protected]:ibproduct/charlymcpcacheserver.git
4 |
5 | ## Architecture Overview
6 |
7 | ### Core Components
8 |
9 | 1. **CacheManager**
10 | - In-memory storage using Map
11 | - LRU eviction strategy
12 | - TTL management
13 | - Memory usage tracking
14 | - Statistics collection
15 |
16 | 2. **MCP Server**
17 | - Tool registration
18 | - Resource endpoints
19 | - Request handling
20 | - Error management
21 |
22 | ### Data Structures
23 |
24 | ```typescript
25 | interface CacheEntry {
26 | value: any; // Cached data
27 | created: number; // Creation timestamp
28 | lastAccessed: number;// Last access timestamp
29 | ttl?: number; // Time-to-live in seconds
30 | size: number; // Memory size estimation
31 | }
32 |
33 | interface CacheStats {
34 | totalEntries: number;
35 | memoryUsage: number;
36 | hits: number;
37 | misses: number;
38 | hitRate: number;
39 | avgAccessTime: number;
40 | }
41 |
42 | interface CacheConfig {
43 | maxEntries?: number;
44 | maxMemory?: number;
45 | defaultTTL?: number;
46 | checkInterval?: number;
47 | statsInterval?: number;
48 | }
49 | ```
50 |
51 | ## Implementation Details
52 |
53 | ### Memory Management
54 |
55 | 1. Size Calculation
56 | ```typescript
57 | private calculateSize(value: any): number {
58 | const str = JSON.stringify(value);
59 | return str.length * 2; // UTF-16 encoding size
60 | }
61 | ```
62 |
63 | 2. LRU Implementation
64 | ```typescript
65 | private enforceMemoryLimit(requiredSize: number): void {
66 | const entries = Array.from(this.cache.entries())
67 | .sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed);
68 |
69 | while (this.stats.memoryUsage + requiredSize > this.config.maxMemory
70 | && entries.length > 0) {
71 | const [key] = entries.shift()!;
72 | this.delete(key);
73 | }
74 | }
75 | ```
76 |
77 | ### MCP Integration
78 |
79 | 1. Tool Registration
80 | ```typescript
81 | this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
82 | tools: [
83 | {
84 | name: 'store_data',
85 | description: 'Store data in cache',
86 | inputSchema: {
87 | type: 'object',
88 | properties: {
89 | key: { type: 'string' },
90 | value: { type: 'any' },
91 | ttl: { type: 'number' }
92 | },
93 | required: ['key', 'value']
94 | }
95 | }
96 | // ... other tools
97 | ]
98 | }));
99 | ```
100 |
101 | 2. Resource Endpoints
102 | ```typescript
103 | this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
104 | resources: [{
105 | uri: 'cache://stats',
106 | name: 'Cache Statistics',
107 | mimeType: 'application/json'
108 | }]
109 | }));
110 | ```
111 |
112 | ## Performance Considerations
113 |
114 | 1. Memory Optimization
115 | - JSON.stringify for size estimation
116 | - LRU eviction for memory limits
117 | - Periodic cleanup of expired entries
118 |
119 | 2. Concurrency
120 | - Map operations are atomic
121 | - Stats updates are synchronized
122 | - Resource access is thread-safe
123 |
124 | 3. Error Handling
125 | - Graceful degradation on memory limits
126 | - Error propagation through MCP protocol
127 | - Automatic recovery mechanisms
128 |
129 | ## Development Guidelines
130 |
131 | 1. Code Style
132 | - TypeScript strict mode
133 | - Async/await for asynchronous operations
134 | - Private methods for internal logic
135 | - Clear error messages
136 |
137 | 2. Testing
138 | - Unit tests for CacheManager
139 | - Integration tests for MCP tools
140 | - Performance benchmarks
141 | - Memory leak detection
142 |
143 | 3. Documentation
144 | - TSDoc comments
145 | - Clear method signatures
146 | - Example usage
147 | - Error scenarios
148 |
149 | ## Future Development
150 |
151 | 1. Performance Enhancements
152 | - More accurate memory tracking
153 | - Optimized data serialization
154 | - Batch operations support
155 |
156 | 2. Feature Additions
157 | - Pattern-based cache invalidation
158 | - Cache warming strategies
159 | - Custom eviction policies
160 |
161 | 3. Monitoring
162 | - Detailed performance metrics
163 | - Debug logging system
164 | - Health check endpoints
165 |
166 | 4. Scaling
167 | - Multi-process support
168 | - Distributed caching
169 | - Cache synchronization
170 |
```
--------------------------------------------------------------------------------
/src/CacheManager.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { CacheEntry, CacheStats, CacheConfig } from './types.js';
2 |
3 | export class CacheManager {
4 | private cache: Map<string, CacheEntry>;
5 | private stats: CacheStats;
6 | private config: Required<CacheConfig>;
7 | private cleanupInterval: ReturnType<typeof setInterval>;
8 | private statsUpdateInterval: ReturnType<typeof setInterval>;
9 |
10 | constructor(config: CacheConfig = {}) {
11 | this.cache = new Map();
12 | this.stats = {
13 | totalEntries: 0,
14 | memoryUsage: 0,
15 | hits: 0,
16 | misses: 0,
17 | hitRate: 0,
18 | avgAccessTime: 0
19 | };
20 |
21 | // Set default configuration
22 | this.config = {
23 | maxEntries: config.maxEntries ?? 1000,
24 | maxMemory: config.maxMemory ?? 100 * 1024 * 1024, // 100MB default
25 | defaultTTL: config.defaultTTL ?? 3600, // 1 hour default
26 | checkInterval: config.checkInterval ?? 60 * 1000, // 1 minute default
27 | statsInterval: config.statsInterval ?? 30 * 1000 // 30 seconds default
28 | };
29 |
30 | // Start maintenance intervals
31 | this.cleanupInterval = setInterval(() => this.evictStale(), this.config.checkInterval);
32 | this.statsUpdateInterval = setInterval(() => this.updateStats(), this.config.statsInterval);
33 | }
34 |
35 | set(key: string, value: any, ttl?: number): void {
36 | const startTime = performance.now();
37 |
38 | // Calculate approximate size in bytes
39 | const size = this.calculateSize(value);
40 |
41 | // Check if adding this entry would exceed memory limit
42 | if (this.stats.memoryUsage + size > this.config.maxMemory) {
43 | this.enforceMemoryLimit(size);
44 | }
45 |
46 | const entry: CacheEntry = {
47 | value,
48 | created: Date.now(),
49 | lastAccessed: Date.now(),
50 | ttl: ttl ?? this.config.defaultTTL,
51 | size
52 | };
53 |
54 | this.cache.set(key, entry);
55 | this.stats.totalEntries = this.cache.size;
56 | this.stats.memoryUsage += size;
57 |
58 | const endTime = performance.now();
59 | this.updateAccessTime(endTime - startTime);
60 | }
61 |
62 | get(key: string): any {
63 | const startTime = performance.now();
64 | const entry = this.cache.get(key);
65 |
66 | if (!entry) {
67 | this.stats.misses++;
68 | this.updateHitRate();
69 | return undefined;
70 | }
71 |
72 | // Check if entry has expired
73 | if (this.isExpired(entry)) {
74 | this.delete(key);
75 | this.stats.misses++;
76 | this.updateHitRate();
77 | return undefined;
78 | }
79 |
80 | // Update last accessed time
81 | entry.lastAccessed = Date.now();
82 | this.stats.hits++;
83 | this.updateHitRate();
84 |
85 | const endTime = performance.now();
86 | this.updateAccessTime(endTime - startTime);
87 |
88 | return entry.value;
89 | }
90 |
91 | delete(key: string): boolean {
92 | const entry = this.cache.get(key);
93 | if (entry) {
94 | this.stats.memoryUsage -= entry.size;
95 | this.cache.delete(key);
96 | this.stats.totalEntries = this.cache.size;
97 | return true;
98 | }
99 | return false;
100 | }
101 |
102 | clear(): void {
103 | this.cache.clear();
104 | this.resetStats();
105 | }
106 |
107 | getStats(): CacheStats {
108 | return { ...this.stats };
109 | }
110 |
111 | private isExpired(entry: CacheEntry): boolean {
112 | return Date.now() > entry.created + (entry.ttl ?? this.config.defaultTTL) * 1000;
113 | }
114 |
115 | private evictStale(): void {
116 | for (const [key, entry] of this.cache.entries()) {
117 | if (this.isExpired(entry)) {
118 | this.delete(key);
119 | }
120 | }
121 | }
122 |
123 | private enforceMemoryLimit(requiredSize: number): void {
124 | // Use LRU strategy to remove entries until we have enough space
125 | const entries = Array.from(this.cache.entries())
126 | .sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed);
127 |
128 | while (this.stats.memoryUsage + requiredSize > this.config.maxMemory && entries.length > 0) {
129 | const [key] = entries.shift()!;
130 | this.delete(key);
131 | }
132 | }
133 |
134 | private calculateSize(value: any): number {
135 | // Rough estimation of memory usage in bytes
136 | const str = JSON.stringify(value);
137 | return str.length * 2; // Approximate UTF-16 encoding size
138 | }
139 |
140 | private updateHitRate(): void {
141 | const total = this.stats.hits + this.stats.misses;
142 | this.stats.hitRate = total > 0 ? (this.stats.hits / total) * 100 : 0;
143 | }
144 |
145 | private updateAccessTime(duration: number): void {
146 | const total = this.stats.hits + this.stats.misses;
147 | this.stats.avgAccessTime =
148 | ((this.stats.avgAccessTime * (total - 1)) + duration) / total;
149 | }
150 |
151 | private resetStats(): void {
152 | this.stats = {
153 | totalEntries: 0,
154 | memoryUsage: 0,
155 | hits: 0,
156 | misses: 0,
157 | hitRate: 0,
158 | avgAccessTime: 0
159 | };
160 | }
161 |
162 | private updateStats(): void {
163 | // Additional periodic stats updates could be added here
164 | this.updateHitRate();
165 | }
166 |
167 | destroy(): void {
168 | if (this.cleanupInterval) clearInterval(this.cleanupInterval);
169 | if (this.statsUpdateInterval) clearInterval(this.statsUpdateInterval);
170 | this.clear();
171 | }
172 | }
173 |
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | #!/usr/bin/env node
2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4 | import {
5 | CallToolRequestSchema,
6 | ErrorCode,
7 | ListResourcesRequestSchema,
8 | ListToolsRequestSchema,
9 | McpError,
10 | ReadResourceRequestSchema,
11 | } from '@modelcontextprotocol/sdk/types.js';
12 | import { CacheManager } from './CacheManager.js';
13 | import fs from 'fs-extra';
14 | import path from 'path';
15 |
16 | class MemoryCacheServer {
17 | private server: Server;
18 | private cacheManager: CacheManager;
19 |
20 | constructor() {
21 | // Load configuration
22 | const configPath = process.env.CONFIG_PATH || path.join(process.cwd(), 'config.json');
23 | const config = fs.existsSync(configPath)
24 | ? fs.readJsonSync(configPath)
25 | : {};
26 |
27 | // Allow environment variable overrides
28 | const finalConfig = {
29 | maxEntries: parseInt(process.env.MAX_ENTRIES as string) || config.maxEntries,
30 | maxMemory: parseInt(process.env.MAX_MEMORY as string) || config.maxMemory,
31 | defaultTTL: parseInt(process.env.DEFAULT_TTL as string) || config.defaultTTL,
32 | checkInterval: parseInt(process.env.CHECK_INTERVAL as string) || config.checkInterval,
33 | statsInterval: parseInt(process.env.STATS_INTERVAL as string) || config.statsInterval
34 | };
35 |
36 | this.server = new Server(
37 | {
38 | name: 'charly-memory-cache-server',
39 | version: '0.1.0',
40 | },
41 | {
42 | capabilities: {
43 | resources: {},
44 | tools: {},
45 | },
46 | }
47 | );
48 |
49 | this.cacheManager = new CacheManager(finalConfig);
50 |
51 | this.setupResourceHandlers();
52 | this.setupToolHandlers();
53 |
54 | // Error handling
55 | this.server.onerror = (error) => console.error('[MCP Error]', error);
56 | process.on('SIGINT', async () => {
57 | await this.close();
58 | process.exit(0);
59 | });
60 | }
61 |
62 | private setupResourceHandlers() {
63 | // List available resources
64 | this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
65 | resources: [
66 | {
67 | uri: 'cache://stats',
68 | name: 'Cache Statistics',
69 | mimeType: 'application/json',
70 | description: 'Real-time cache performance metrics',
71 | },
72 | ],
73 | }));
74 |
75 | // Handle resource reads
76 | this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
77 | if (request.params.uri === 'cache://stats') {
78 | return {
79 | contents: [
80 | {
81 | uri: request.params.uri,
82 | mimeType: 'application/json',
83 | text: JSON.stringify(this.cacheManager.getStats(), null, 2),
84 | },
85 | ],
86 | };
87 | }
88 |
89 | throw new McpError(
90 | ErrorCode.InvalidRequest,
91 | `Unknown resource: ${request.params.uri}`
92 | );
93 | });
94 | }
95 |
96 | private setupToolHandlers() {
97 | this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
98 | tools: [
99 | {
100 | name: 'store_data',
101 | description: 'Store data in the cache with optional TTL',
102 | inputSchema: {
103 | type: 'object',
104 | properties: {
105 | key: {
106 | type: 'string',
107 | description: 'Unique identifier for the cached data',
108 | },
109 | value: {
110 | type: 'any',
111 | description: 'Data to cache',
112 | },
113 | ttl: {
114 | type: 'number',
115 | description: 'Time-to-live in seconds (optional)',
116 | },
117 | },
118 | required: ['key', 'value'],
119 | },
120 | },
121 | {
122 | name: 'retrieve_data',
123 | description: 'Retrieve data from the cache',
124 | inputSchema: {
125 | type: 'object',
126 | properties: {
127 | key: {
128 | type: 'string',
129 | description: 'Key of the cached data to retrieve',
130 | },
131 | },
132 | required: ['key'],
133 | },
134 | },
135 | {
136 | name: 'clear_cache',
137 | description: 'Clear specific or all cache entries',
138 | inputSchema: {
139 | type: 'object',
140 | properties: {
141 | key: {
142 | type: 'string',
143 | description: 'Specific key to clear (optional - clears all if not provided)',
144 | },
145 | },
146 | },
147 | },
148 | {
149 | name: 'get_cache_stats',
150 | description: 'Get cache statistics',
151 | inputSchema: {
152 | type: 'object',
153 | properties: {},
154 | },
155 | },
156 | ],
157 | }));
158 |
159 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
160 | try {
161 | switch (request.params.name) {
162 | case 'store_data': {
163 | const { key, value, ttl } = request.params.arguments as {
164 | key: string;
165 | value: any;
166 | ttl?: number;
167 | };
168 | this.cacheManager.set(key, value, ttl);
169 | return {
170 | content: [
171 | {
172 | type: 'text',
173 | text: `Successfully stored data with key: ${key}`,
174 | },
175 | ],
176 | };
177 | }
178 |
179 | case 'retrieve_data': {
180 | const { key } = request.params.arguments as { key: string };
181 | const value = this.cacheManager.get(key);
182 | if (value === undefined) {
183 | return {
184 | content: [
185 | {
186 | type: 'text',
187 | text: `No data found for key: ${key}`,
188 | },
189 | ],
190 | isError: true,
191 | };
192 | }
193 | return {
194 | content: [
195 | {
196 | type: 'text',
197 | text: JSON.stringify(value, null, 2),
198 | },
199 | ],
200 | };
201 | }
202 |
203 | case 'clear_cache': {
204 | const { key } = request.params.arguments as { key?: string };
205 | if (key) {
206 | const success = this.cacheManager.delete(key);
207 | return {
208 | content: [
209 | {
210 | type: 'text',
211 | text: success
212 | ? `Successfully cleared cache entry: ${key}`
213 | : `No cache entry found for key: ${key}`,
214 | },
215 | ],
216 | };
217 | } else {
218 | this.cacheManager.clear();
219 | return {
220 | content: [
221 | {
222 | type: 'text',
223 | text: 'Successfully cleared all cache entries',
224 | },
225 | ],
226 | };
227 | }
228 | }
229 |
230 | case 'get_cache_stats': {
231 | const stats = this.cacheManager.getStats();
232 | return {
233 | content: [
234 | {
235 | type: 'text',
236 | text: JSON.stringify(stats, null, 2),
237 | },
238 | ],
239 | };
240 | }
241 |
242 | default:
243 | throw new McpError(
244 | ErrorCode.MethodNotFound,
245 | `Unknown tool: ${request.params.name}`
246 | );
247 | }
248 | } catch (error) {
249 | return {
250 | content: [
251 | {
252 | type: 'text',
253 | text: error instanceof Error ? error.message : String(error),
254 | },
255 | ],
256 | isError: true,
257 | };
258 | }
259 | });
260 | }
261 |
262 | async run() {
263 | const transport = new StdioServerTransport();
264 | await this.server.connect(transport);
265 | console.error('Memory Cache MCP server running on stdio');
266 | }
267 |
268 | async close() {
269 | this.cacheManager.destroy();
270 | await this.server.close();
271 | }
272 | }
273 |
274 | const server = new MemoryCacheServer();
275 | server.run().catch(console.error);
276 |
```