Skip to main content
Glama

Systems MCP

by lethain
readme.md10.5 kB
# Systems `systems` is a set of tools for describing, running and visualizing [systems diagrams](https://lethain.com/systems-thinking/). Installation directions are below, and then get started by [working through the tutorial](./docs/tutorial.md) or reading through the [Jupyter notebook example](./notebooks/hiring.ipynb) example. For a more in-depth look at the system syntax, please read [the syntax specification](./docs/spec.md). ## Quickest start Follow the installation instructions below, then write a system definition such as: Start(10) Start > Middle @ 2 Middle > End You can then evaluate your system (use `--csv` for an importable format): cat tmp.txt | systems-run -r 3 Start Middle End 0 10 0 0 1 8 2 0 2 6 3 1 3 4 4 2 See [the tutorial](./docs/tutorial.md) for more detailed starting information. ## Running in code It's also possible to write code to run your model, rather than rely on the command line tool. For example: from systems.parse import parse def results_for_spec(spec, rounds): model = parse(spec) results = model.run(rounds=rounds) return model, results spec = """Start(10) Start > Middle @ 2 Middle > End""" model, results = results_for_spec(spec, 10) print(results) # outputs: [{'Start': 10, 'Middle': 0, 'End': 0}, {'Start': 8, 'Middle': 2, 'End': 0}, ...] This pattern is particularly useful when running from inside of a Jupyter Notebook, such as the examples in [`lethain/eng-strategy-models`](https://github.com/lethain/eng-strategy-models). ## Installation To install via PyPi: pip install systems To install for local development: git clone https://github.com/lethain/systems.git cd systems python3 -m venv ./env source ./env/bin/activate python setup.py develop Run tests via: python3 -m unittest tests/test_*.py Or run a single test via: python3 tests/test_parse.py TestParse.test_parse_complex_formula Please open an Github issue if you run into any problems! ## Jupyter notebooks Likely the easiest way to iterate on a model is within a Jupyter notebook. See an [example notebook here](./notebooks/hiring.ipynb). To install, follow the installation steps above, and followed by: # install graphviz brew install graphviz # install these additional python packages pip install jupyter pandas matplotlib ## Using the command line tools There are four command line tools that you'll use when creating and debugging systems/ `systems-run` is used to run models: $ cat examples/hiring.txt | systems-run -r 3 PhoneScreens Onsites Offers Hires Employees Departures 0 0 0 0 0 5 0 1 25 0 0 0 5 0 2 25 12 0 0 5 0 3 25 12 6 0 5 0 `systems-viz` is used to visualize models into [Graphviz](https://www.graphviz.org/): $ cat examples/hiring.txt | systems-viz // Parsed digraph { rankdir=LR 0 [label=Candidates] 1 [label=PhoneScreens] // etc, etc, some other stuff } Typically you'll pipe the output of `systems-viz` into `dot`, for example $ cat examples/hiring.txt | systems-viz | dot -Tpng -o tmp.png `systems-format` reads in a model, tokenizes it and formats the tokens into properly formatted results. This is similar to `gofmt`, and could be used for ensuring a consistent house formatting style for your diagrams. (It was primarily implemented to support generating human readable error messages instead of surfacing the tokens to humans when errors arise.) $ cat examples/hiring.txt | systems-fmt [Candidates] > PhoneScreens @ 25 PhoneScreens > Onsites @ 0.5 # etc etc `systems-lex` generates the tokens for a given system file. This is typically most useful when you're extending the lexer to support new types of functionality, but can also be useful for other kinds of debugging: $ cat examples/hiring.txt | systems-lex ('lines', [('line', 1, [('comment', '# wrap with [] to indicate an infinite stock that')]), ('line', 2, [('comment', "# isn't included in each table")]), ('line', 3, [('comment', '# integers are implicitly steady rates')]), ('line', 4, [('infinite_stock', 'Candidates', ('params', [])), ('flow_direction', '>'), ('stock', 'PhoneScreens', ('params', ())), ('flow_delimiter', '@'), ('flow', '', ('params', (('formula', [('whole', '25')]),)))]), ... ] ) ## Error messages The parser will do its best to give you a useful error message. For example, if you're missing delimiters: cat examples/no_delim.txt | systems-run line 1 is missing delimiter '>': "[a] < b @ 25" At worst, it will give you the line number and line that is creating an issue: cat examples/invalid_flow.txt | systems-run line 1 could not be parsed: "a > b @ 0..2" ## Uploading distribution If you are trying to install this on PyPi, the steps are roughly: python3 -m pip install --user --upgrade pip python3 -m pip install --user --upgrade wheel python3 -m pip install --user --upgrade twine python3 setup.py sdist bdist_wheel twine upload --repository-url https://upload.pypi.org/legacy/ dist/* That should more or less work. :) ## Syntax Specification The full the syntax specification is available in [./docs/spec.md](./docs/spec.md), and is replicated here to make this library easier to drive with an LLM. --- This file specifies the language used for describing systems in `systems`. There are three primary kinds of objects to specify: * `stocks` hold values, and * `flows` transition values from one stock to another. * finally, `formula` are used to describe initial and maximum values for stocks, and the magnitude of flows. ## Specifying stocks Stocks are specified on their own line, or implicitly in flow declarations: MyStock This would create a stock named `MyStock` with an initial value of zero and a maximum value of infinity: OtherStock(10) You can also specify maximum values: ThirdStock(0, 10) This would create `ThirdStock` with an initial value of zero, and a maximum value of ten. Going back to `OtherStock` for a moment, you can also use the special literal `inf` to explicitly specify its maximum value: OtherStock(10, inf) This is a more explicit way to specify a stock with an infinite maximum. Generally it's a strange indicator if you're using the `inf` literal directly, and instead you'd use the special syntax for infinite flows: [InfiniteFlow] This `InfiniteFlow` would have initial and maximum values of infinity. Without going too far into the details, initial and maximums can be specified using any legal formula, more on formulas below: Managers(2) Engineers(Managers * 4, Managers * 8) In many cases, though, you'll end up specifying your stocks inline in your flows, as opposed to doing them on their own lines, but the syntax is the same. ## Flows For example, this would have both `a` and `b` would initialize at zero, and both would have infinite maximum values, in addition there would be a flow of one unit per round from `a` to `b` (assuming that `a` is above zero): a > b @ 1 In the above example, `a` has an initial value of zero, so it would never do anything. Most working systems address that problem by starting with an infinite stock: [a] > b @ 5 b > [c] @ 3 In the above, `a` and `c` would be infinite, and `b` would start with a value of zero. You can also solve the empty start problem by specifying non-zero initial values for your stocks: a(10) > b(3) @ 5 b > c(12) @ 1 c > a In this example, `a` is initialized at 10, `b` at 3, and `c` at 12. Note that you don't have to set the value at first reference. It is legal to initialize a value at a later definition of a stock, e.g. this is fine: a(1) > b @ 5 b(2) > c @ 3 c(3) > a @ 1 However, it *is* illegal to initialize the same stock multiple times. a(1) > b(2) @ 1 b(3) > a @ 1 This will throw an error, because you can't initialize `b` twice with different values! ## Rates, Conversions and Leaks Each line specifies two nodes and the link between them. Links are described following the `@` character. The most common type of flow is a `rate`, which is a fixed transfer of values in one stock to another. For example, moving two units per round between `a` and `b`: # these are equivalent a > b @ 2 a > b @ Rate(2) Up to two units will be transfered from `a` to `b` each round. Another common kind of flow is the `conversion` flow, which takes the entire contents of the source stock and multiplies that value against the conversion rate, adding the result to the next flow. # these are equivalent a(10) > b @ 0.5 a(10) > b @ Conversion(0.5) The above would multiple `0.5` against `10` and move `5` units to `b`, with the other `5` units being lost to the conversion rate (e.g. disappearing). A common example of a conversion rate would be the offer acceptance rate in a [hiring funnel](https://lethain.com/hiring-funnel/). The third kind of flow is the `leak`, which combines properties of the `rate` and `conversion` flows. It moves a fixed percentage of the source flow into the destination flow, while leaving the remainder intact. a(10) > b @ Leak(0.2) Considering the difference between the `conversion` and `leak`, if the above were a `conversion`, then the value of `a` after one round would be `0`, but if it's a `leak`, then the value would be `8`. ## Formulas Any flow value, initial value and maximum value can be a formula: Recruiters(3) Engineers(Managers * 4, Managers * 8) [Candidates] > Engineers @ Recruiters * 6 [Candidates] > Managers @ Recruiters * 3 The above system shows that `Engineers` has an initial value of `Managers * 4`, a maximum value of `Managers * 8` and then shows that both `Engineers` and `Managers` grow at multiples of the value of the `Recruiters` stock. This is also a good example of using the `Recruiters` stock as a variable, as it doesn't' actually change over time.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lethain/systems-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server